Ruby 2.0 のRefinementについて、以下の仕様(Refinementのモジュール/クラス内部スコープ) は 2.0 では入りません。
- Refinementの有効範囲について、「
Module#refine
が宣言されたModuleでは有効」である -
Class#using
により、当該クラス内部でのみRefinementを有効化できる
また、
require "refinement"
は必要ありません。
以下の仕様は正しいものとなります。
- トップレベルに定義された
using
を利用することでRefinementは有効になる - Refinementの変更のスコープはファイル内のみとなる
よって、
- 本誌 128 ページの左段と右段一番上のコードはそのままでは動作しないものとなっています。
- 本誌 128 ページの右段中部、「特定の範囲で外部コマンド実行を禁止する」のコードは
require "refinement"
の箇所以外そのまま利用できます(トップレベルの関数的メソッドを Object のrefineで上書きすることが可能です)。
代替コードを以下に示します。
main.rb
def assert_equal(a, b)
puts "#{a} should be #{b}"
end
module InchAvailable
refine Fixnum do
def inch
self * 2.54
end
alias inches inch
end
end
require './sample_class'
begin
p 3.inches
rescue => e
puts "*** should raise error outside", e.class, e
end
puts "*** ok if defined inside, but used outside"
assert_equal SampleClass.get_price_from_inch(10), 254.0
using InchAvailable
puts "*** ok after main.using"
assert_equal 3.inches, 7.62
sample_class.rb
using InchAvailable
puts "*** inside sample_class.rb"
class SampleClass
assert_equal 3.inches, 7.62
def self.get_price_from_inch(size)
10 * size.inch
end
end
RefinementsSpec というwikiの記事も併せてご参照ください。