114

I am new to Ruby. I'm looking to import functions from a module that contains a tool I want to continue using separately. In Python I would simply do this:

def a():
    ...
def b():
    ...
if __name__ == '__main__':
    a()
    b()

This allows me to run the program or import it as a module to use a() and/or b() separately. What's the equivalent paradigm in Ruby?

Imagist
  • 18,086
  • 12
  • 58
  • 77
  • possible duplicate of [Run a Ruby library from the command-line](http://stackoverflow.com/questions/487086/run-a-ruby-library-from-the-command-line) – Andrew Grimm Aug 17 '11 at 03:18

3 Answers3

150

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.

Matchu
  • 83,922
  • 18
  • 153
  • 160
  • 5
    What's the reasoning behind keeping modules and scripts separate, out of curiosity? – Imagist Feb 12 '10 at 02:43
  • 5
    I think it's just what Rubyists prefer to do. A module definition is a module definition. If you want to take some action with that module, fine, but the action you're taking *isn't* a module definition. – Matchu Feb 12 '10 at 02:48
  • 10
    It's handy, though, for testing things -- you can put module tests in there and run them just from the module file without any wrapper. – ebneter Feb 12 '10 at 03:11
  • 3
    @Imagist and @ebneter Or the other way around: the script is a single module that is intended to be run from the commandline, but you also want to be able to test it in parts and have the test in a seperate module. In that case, __NAME__ == $0 is invaluable. – Confusion Feb 24 '10 at 09:56
  • 16
    I haven't seen this either, but it isn't frowned upon. The official Ruby docs use it: http://www.ruby-lang.org/en/documentation/quickstart/4/ – cflewis Aug 07 '10 at 07:28
  • I'd use File.expand_path(path) on them to take into account things like ./my-program or running it from another directory... – rosenfeld Jun 22 '16 at 13:10
  • 1
    Perfectly standard solution as for today. But **`$PROGRAM_NAME`** is preferred over `$0` in conformity with **The Ruby Style Guide** https://rubystyle.guide/#no-cryptic-perlisms – Mario G Jun 29 '21 at 12:25
12

If stack trace is empty, we can start executing to the right and left. I don't know if that's used conventionally or unconventionally since I'm into Ruby for about a week.

if caller.length == 0
  # do stuff
end

Proof of concept:

file: test.rb

#!/usr/bin/ruby                                                                 

if caller.length == 0
  puts "Main script"
end

puts "Test"

file: shmest.rb

#!/usr/bin/ruby -I .                                                            

require 'test.rb'

puts "Shmest"

Usage:

$ ./shmest.rb 
Test
Shmest

$ ./test.rb
Main script
Test
uKolka
  • 36,422
  • 4
  • 33
  • 44
11
if $PROGRAM_NAME == __FILE__
  foo()
  bar()
end 

is preferred by Rubocop over this:

if __FILE__ == $0
    foo()
    bar()
end
ablarg
  • 2,400
  • 1
  • 24
  • 32