Should I define a main method in my ruby scripts?
I usually use
if __FILE__ == $0
x = SweetClass.new(ARGV)
x.run # or go, or whatever
end
So yes, you can. It just depends on what you are doing.
Is there a main method in Ruby like in C?
@Hauleth's answer is correct: there is no main
method or structure in Ruby. I just want to provide a slightly different view here along with some explanation.
When you execute ruby somefile.rb
, Ruby executes all of the code in somefile.rb
. So if you have a very small project and want it to be self-contained in a single file, there's absolutely nothing wrong with doing something like this:
# somefile.rb
class MyClass
def say_hello
puts "Hello World"
end
end
def another_hello
puts "Hello World (from a method)"
end
c = MyClass.new
c.say_hello
another_hello
It's not that the first two blocks aren't executed, it's just that you don't see the effects until you actually use the corresponding class/method.
The if __FILE__ == $0
bit is just a way to block off code that you only want to run if this file is being run directly from the command line. __FILE__
is the name of the current file, $0
is the command that was executed by the shell (though it's smart enough to drop the ruby
), so comparing the two tells you precisely that: is this the file that was executed from the command line? This is sometimes done by coders who want to define a class/module in a file and also provide a command-line utility that uses it. IMHO that's not very good project structure, but just like anything there are use cases where doing it makes perfect sense.
If you want to be able to execute your code directly, you can add a shebang line
#!/usr/bin/env ruby
# rest of somefile.rb
and make it executable with chmod +x somefile.rb
(optionally rename it without the .rb extension). This doesn't really change your situation. The if __FILE__ == $0
still works and still probably isn't necessary.
Edit
As @steenslag correctly points out, the top-level scope in Ruby is an Object
called main
. It has slightly funky behavior, though:
irb
>> self
=> main
>> self.class
=> Object
>> main
NameError: undefined local variable or method `main' for main:Object
from (irb):8
Don't worry about this until you start to dig much deeper into the language. If you do want to learn lots more about this kind of stuff, Metaprogramming Ruby is a great read :)
Where do I write the main function in Ruby?
There is no such thing in Ruby. The interpreter executes code from top to bottom so your main script is implicitly the body of "main". For example, suppose you have two files script_a.rb
and script_b.rb
. And suppose the contents of script_a.rb
is as follows:
require_relative './script_b'
puts 1 + 1
Now if you run ruby script_a.rb
what you will get in terms of actual code execution will be as follows: Find script_b.rb
, execute the contents of script_b.rb
, execute puts 1 + 1
.
What is main in Ruby?
Everything in Ruby occurs in the context of some object. The object at the top level is called "main". It's basically an instance of Object with the special property that any methods defined there are added as instance methods of Object (so they're available everywhere).
So we can make a script consisting entirely of:
puts object_id
@a = 'Look, I have instance variables!'
puts @a
and it will print "105640" and "Look, I have instance variables!".
It's not something you generally need to concern yourself with, but it is there.
Ruby methods at bottom of script?
You can do initializing code in one or more BEGIN-blocks (inherited from Perl, which inherited them from awk).
can_i_do_this? #=>yes
BEGIN {
def can_i_do_this?
puts "yes"
end
}
And for completeness, there are also END-blocks:
END {
can_i_do_this? #=> yes
}
def can_i_do_this?
puts "yes"
end
Ruby - when I should use parenthesis or not when calling a function/method
There isn't an official standard for Ruby code best practices. However, a set of preferred styles has evolved in the Ruby community. It's a good idea to follow those preferred styles, just because it makes your code more easily readable by other Ruby programmers.
Nick Roz has given you a link to the style guide. I would also recommend that you consider installing and using rubocop. It will give you feedback on when and when not to parenthesize arguments, many other formatting matters such as proper indenting, and which of the often several different syntax options to choose in a particular situation.
To answer your specific question about whether or not to use parentheses for method arguments, the answer is yes, in general. Exceptions are, as the guide says, "methods that have 'keyword' status in Ruby." An example is puts
(actually the Kernel.puts
method). Most people don't use parentheses here, but the guide states that they are optional.
Another example, as Nick has said (although "methods with keyword arguments" isn't quite correct; in that case the arguments are symbols that represent methods rather than keywords), is attr_accessor
, which is actually Module.attr_accessor
.
So, as a general rule, if it looks like a "command" (a "keyword," if you will), but is actually a method, omit the parentheses. Otherwise, use them. And if you're not sure of the difference, get in the habit of using rubocop.
Scripting in Ruby
When I write a one off script, I often wrap it in a class. You've pointed out some advantages of doing this including reuse and cleaner documentation.
I find that there are several levels of polish for scripts depending on how they are going to be used. If the script is run once and never used again, I may not wrap it in a class. If it's important (taking backups of production systems), it's probably worth putting it in full gem form and writing tests. Somewhere in the middle is the single purpose class. Generally this means you're taking the code that's not in a method and putting it in the class constructor.
This:
#!ruby
def amethod(i)
i+1
end
ARGF.each do |l|
if l.chomp.to_i > 0
puts amethod(l.chomp.to_i)
end
end
Becomes:
#!ruby
class OneAdder
def amethod(i)
i+1
end
def initialize
ARGF.each do |l|
if l.chomp.to_i > 0
puts amethod(l.chomp.to_i)
end
end
end
end
OneAdder.new
execute a method in a ruby file
A couple of reasons this doesn't work as you have written it.
- The method foo hasn't been declared before you attempt to call it.
- The method foo, as you have declared it, is an instance method. You're not invoking it on an instance of the class.
This would work:
class Bar
def self.foo
end
foo
end
As others have said, though, you probably don't need to wrap this in a class.
Needing forward declaration in Ruby
You just need the functions you call to be defined when your main
function runs, not when it's defined. So, the easiest solution is to write the main
function at the script's beginning, but call it at the end.
def main
foo(42)
bar(24)
end
# definitions of foo and bar
main
Related Topics
How to Export Environment Variable Permanently Using Ruby
Message Queues in Ruby on Rails
Rails: Good Rspec2 Example Usage? (Also: Cucumber, Pickle, Capybara)
Ruby - Using Class_Eval to Define Methods
Ruby Mixins: Extend and Include
How to Time an Operation in Milliseconds in Ruby
How to Create a Ruby Date Object from a String
Partial Haml Templating in Ruby Without Rails
Why Does Ruby "Script/Generate" Return "No Such File or Directory"
Troubleshooting Ssl Certificates, Ruby, MAC Os X Yosemite
How to List All Versions of a Gem Available at a Remote Site
What's the Difference Between Request.Remote_Ip and Request.Ip in Rails
Generating Unique, Hard-To-Guess "Coupon" Codes
"Uninitialized Constant" Error When Including a Module
In Ruby, When Should You Use Self. in Your Classes