1
Help us understand the problem. What are the problem?

posted at

updated at

Ruby でも Python の if __name__ == '__main__' がやりたい

やりたいこと

  • Ruby ファイルを ruby コマンドや bin/rails runner コマンドなどで直接実行した場合のみ、特定のコードを実行したい。
    • 別の Ruby ファイルから require した場合は実行したくない。
    • Python ファイルでよく見る以下の記述のようなことがやりたい。
def hello_world():
    print('Hello World 🌍')

if __name__ == '__main__': 
    hello_world() 

方法

if __FILE__ == $PROGRAM_NAME
end

を使う。

$ ruby body_mass_index.rb

のように Ruby ファイルを直接実行した場合だけ単体テストを実行したい。

body_mass_index.rb
require 'delegate'

class BodyMassIndex < DelegateClass(Float)
  def initialize(height:, weight:)
    value = weight.fdiv(height ** 2) * (100 ** 2)
    super(value)
  end
end

if __FILE__ == $PROGRAM_NAME
  require 'minitest'
  require 'minitest/autorun'

  class BodyMassIndexTest < Minitest::Test
    def test_round
      bmi = BodyMassIndex.new(height: 170, weight: 60)

      assert_equal(21, bmi.round)
      assert_equal(20.8, bmi.round(1))
      assert_equal(20.76, bmi.round(2))
    end
  end
end
$ ruby body_mass_index.rb
Run options: --seed 12009

# Running:

.

Finished in 0.000706s, 1416.4306 runs/s, 4249.2918 assertions/s.

1 runs, 3 assertions, 0 failures, 0 errors, 0 skips

解説

  • $PROGRAM_NAME は現在実行中の Ruby スクリプトの名前の文字列。
    • $0 と同じ。
  • __FILE__ は現在実行しているファイルの名前の文字列。

たとえば以下の calculate_bmi.rb を ruby コマンドで実行した場合は

/Users/quanon/workspace/calculate_bmi.rb
require 'optparse'
require './body_mass_index'

opts = ARGV.getopts('', 'height:', 'weight:')
bmi = BodyMassIndex.new(height: opts.fetch('height').to_f, weight: opts.fetch('weight').to_f)
puts("あなたの BMI は #{bmi.round(2)} です。")
$ ruby calculate_bmi.rb --height 171.8 --weight 64.5
あなたの BMI は 21.85 です。
__FILE__ $PROGRAM_NAME
"/Users/quanon/workspace/body_mass_index.rb" "calculate_bmi.rb"

となる。一方で同じディレクトリにある body_mass_index.rb を ruby コマンドで実行した場合は

__FILE__ $PROGRAM_NAME
"body_mass_index.rb" "body_mass_index.rb"

となる。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?