Command line and argument processing - ruby

Good morning...evening.
The problem is about calling method with given argument straightaway after typing in command line:
$ ruby my_class.rb someString
I have got a file my_class.rb with code:
class MyClass
p ARGV
end
and that works, but I would like to use a method to print that input:
class MyClass
def print_me(string)
p string
end
end
Is it even possible to do it without specifying class and method in command line and keep it that way?
$ ruby my_class.rb someString

Yes, just define your class and then call it with the arguments like this:
class MyClass
def print_me(string)
p string
end
end
MyClass.new.print_me(ARGV[0])
You can put the last line in a different file that requires your class definition. But this just changes how you manage your code.

Related

Execute ruby method from command-line

I have the following class in Ruby in the file test_class.rb:
class TestClass
def test_verify_one
# DO SOME
end
def test_verify_two
# DO SOME
end
end
To execute this class I send two parameters to the terminal, ENVIRONMENT and LANGUAGE.
So... to call from terminal I use:
ruby test_class.rb ENVIRONMENT LANGUAGE
This executes both methods.
I want to execute only one.
I tried the following:
ruby -r "test_class.rb" -e "TestClass.test_verify_one" ENVIRONMENT LANGUAGE
but it is not working.
Can you help me?
Within the same folder as test_class.rb, run the ruby command with the following command syntax:
ruby -I . -r "test_class" -e "TestClass.test_verify_one" arg1 arg2
Breaking this command down we get:
-I . Include current directory in $LOAD_PATH so we can use require
-r Require a file named test_class within the $LOAD_PATH. This is possible because we included the current directory in our load path above (.rb extension is optional here).
-e Same as you've provided, evaluates the following code.
Now, if we call ARGV within that method we should get arg1 and arg2 on separate lines:
#...
def self.test_verify_one
puts ARGV
end
#...
If you want your first method to take the variables you're passing to it you need to define your first method to take two variables, like so:
class TestClass
def test_verify_one (var1, var2)
# DO SOME
end
def test_verify_two
# DO SOME
end
end
You will then need to put a condition into your second which causes it to only execute under the conditions you want it to... or just comment it out if you don't need it at the moment. So, for example, if you only wanted test 2 to fire when variables were not passed in, your code would look something like this:
class TestClass
def test_verify_one (var1, var2)
# DO SOME
end
def test_verify_two (var1, var2)
if (var1 and var2) defined? nil
# DO SOME
end
end

Instantiate class dynamically using filename

my question is that if i have a class CSVWriter inside a file named csv_writer.rb, then can i instantiate this class using my filename dynamically.
I did tried using Object.const_get() method but it takes the name of the class as string as argument.
So is there anyway to do that in ruby
Thanks
You can use the __FILE__ constant to get the name of the file.
# foo.rb
puts __FILE__
Output
"foo.rb"
Knowing this, you could do something like
# csv_writer.rb
class CsvWriter
def initialize
puts "hello"
end
end
klass = Object.const_get(
File::basename(__FILE__, ".rb")
.split("_")
.map(&:capitalize)
.join("")
)
klass.new
Output
"hello"
PS there's no programmatic way to convert csv_writer to CSVWriter. How would ruby know to capitalize csv to CSV (all-caps) but writer to only Writer?

Ruby - Overriding string methods in a separate file

I have a file, 'example.rb', where I want to use custom methods on String by overriding the string class.
I know this can be done as
puts "abcd".twice
class String
def twice
self*2
end
end
But I want to have the custom methods definition in another file, say 'my_String.rb'. How do I do this?
Do your monkey patching in "my_string.rb" (or whatever) and have the file required in your script.
# my_string.rb
class String
def twice
self*2
end
end
# my_super_script.rb
require 'my_string.rb' # Assuming both these files are in the same folder
puts "abcd".twice
You simply put the String class opening method in my_string.rb and in your code you do:
require 'my_string'

How to include/require/load a file in ruby with instance variables

I would like to put a large variable definition in a separate file for the sake of getting it out of the way. I must be doing something wrong though, because my puts call isn't putting anything out.
my_class.rb:
class foobar
def initialize
require 'datafile.rb'
puts #fat_data
end
end
datafile.rb:
#fat_data = [1,2,3,4,5,6,7,8,9,10]
Can you use require this way?
You can do something like this:
my_class.rb:
class Foobar
def initialize
init_fat_data
puts #fat_data
end
end
datafile.rb:
class Foobar
private
def init_fat_data
#fat_data = [1,2,3,4,5,6,7,8,9,10]
end
end
Or, perhaps, change class Foobar in datafile.rb to module MyData and then include the module to Foobar class in my_class.rb.
If you just want to get the data out of the class definition, you could also use __END__ and DATA:
Useless Ruby Tricks: DATA and __END__

Re-define File::dirname ruby method

I'm trying to redefine the File.dirname method to first change %20s to spaces. But the following gives me an error
class File
old_dirname = instance_method(:dirname)
define_method(:dirname) { |s|
s = s.gsub("%20"," ")
old_dirname.bind(self).call(s)
}
end
This trhows a NameError exception: undefined method 'dirname' for class 'File'
What is the right way to do this?
As Chuck already wrote, File::dirname is a singleton method of the File class object (or more precisely an instance method of the File class object's metaclass), not an instance method of the File class.
So, you have to open up File's metaclass, not the File class itself:
#!/usr/bin/env ruby
class << File
old_dirname = instance_method :dirname
define_method :dirname do |*args|
old_dirname.bind(self).(*args).gsub '%20', ' '
end
end
require 'test/unit'
class TestFileDirname < Test::Unit::TestCase
def test_that_it_converts_percent20_to_space
assert_equal '/foo bar/baz', File.dirname('/foo%20bar/baz/quux.txt')
end
end
However, I agree with #sheldonh: this breaks the API contract of File::dirname.
Just be careful.
You're changing the behaviour of the method, not just its implementation. This is generally poor practice, because it weakens the value of the API as a dependable contract.
Instead, consider transforming the input closer to the point of receipt.
dirname is a class method of File, not an instance method, so you're just defining a new instance method. Also, the idiomatic way to alias a method is with alias. So:
class <<File
alias old_dirname dirname
def dirname(f)
old_dirname(f.gsub("%20", " "))
end
end
The class <<whatever syntax adds methods to an individual object — in this case, the File class.

Resources