def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
attr_name
変数が等しい場合、たとえば、 "params"
. これは実際には次のように変換されます。
def params=(attr_name)
@params = attr_name
@params_history = [nil] if @params_history.nil?
@params_history << attr_name
end
なぜそれが起こるのですか?文字列補間と呼ばれるもののため。#{something}
String 内に記述something
すると、その String 内で評価され、置き換えられます。
また、上記のコードが文字列ではないのに機能するのはなぜですか?
答えは、あるからです!
Ruby にはさまざまな方法があります。一部のリテラルには、次のような代替構文があります。同じまたは対応する終了区切り記号を使用する限り、どこに任意の区切り記号を使用できます%w{one two three}
。したがって、または{}
である可能性があり、それらはすべて機能します。%w\one two three\
%w[one two three]
それ%w
は配列%Q
用で、二重引用符で囲まれた文字列用です。それらすべてを見たい場合は、これをご覧になることをお勧めします: http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html
さて、そのコードで
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name # create the attribute's getter
attr_reader attr_name+"_history" # create bar_history getter
class_eval %Q{ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # STRING BEGINS
def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # STRING ENDS
end
end
String 補間のある部分全体が a 内にあることがわかります%Q{ }
。つまり、ブロック全体が二重引用符で囲まれた大きな文字列です。そのため、文字列を eval に送信する前に、文字列補間が正常に機能します。