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.
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
.
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.
`if __name__ == '__main__'` equivalent in Ruby
From the Ruby I've seen out in the wild (granted, not a ton), this is not a standard Ruby design pattern. Modules and scripts are supposed to stay separate, so I wouldn't be surprised if there isn't really a good, clean way of doing this.
EDIT: Found it.
if __FILE__ == $0
foo()
bar()
end
But it's definitely not common.
Instance variables on Ruby main class
@name
is an instance variable, @@name
would be a class variable.
When you define an instance variable outside any explicit class definition, you implicitly are inside the Object
space.
➜ ~ irb
2.1.5 :001 > self.class
=> Object
2.1.5 :002 >
Object
is an object, more or less like a custom object. Therefore, when you created
@name = 'learning metaprogramming!'
the instance variable @name
exists in the scope of the Object
. The method definition happens in the same scope, hence you have accesso the instance variable.
What are the rules for `self` in a top-level method?
All methods defined in the context of main
object, will become [private] methods on Object
. And since everything is an Object, this method will be available everywhere. And this is also why self
is changing based on where you call it from: those are all different objects, but they also all inherit this method.
private_methods.include?(:who_am_i) # => true
foo # => "main"
A.private_methods.include?(:who_am_i) # => true
A.foo # => "A"
A.new.private_methods.include?(:who_am_i) # => true
A.new.foo # => "#<A:0x00007feaad034e00>"
Ruby class methods. Is it getting called on main object?
What is hello being called on?
Whenever there isn't an explicit receiver, the receiver is self
. So the call is implicitly:
self.hello
... where self
is the class Test
, on which you have just defined the self.hello
method.
goodbye
is not found because it is defined on an instance of class Test
, not the class itself, where it's currently called.
Related Topics
How to Redirect to a 404 in Rails
How to Make --No-Ri --No-Rdoc the Default For Gem Install
Oo Design in Rails: Where to Put Stuff
How to Get Argument Names Using Reflection
Why Does String Interpolation Work in Ruby When There Are No Curly Braces
Block Definition - Difference Between Braces and Do-End
Best Way to Convert Strings to Symbols in Hash
Adding a Directory to $Load_Path (Ruby)
How to Convert a Unix Timestamp (Seconds Since Epoch) to Ruby Datetime
Double Colons Before Class Names in Ruby
Why Doesn't Ruby Support I++ or I-- (Increment/Decrement Operators)
How to Get a Random Number in Ruby
Optional Argument After Splat Argument