やりたいこと
- 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" |
となる。
参考
-
変数と定数 (Ruby 3.1 リファレンスマニュアル)
-
__FILE__
は「擬似変数」と呼ばれる変数のひとつらしい。
-
- $0 (Ruby 3.1 リファレンスマニュアル)