0

私のコードには#、セクションにシンボルがありclass_evalます。これは私にとって異質なのですが、どういう意味ですか?

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{
def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
}
  end
end
4

3 に答える 3

4

この機能は文字列補間と呼ばれます。それが効果的に行うことは#{attr_name}attr_name実際の値で置き換えることです。投稿したコードは、ユースケースの1つを示しています-実行時に一般的な名前の変数を使用する場合。

次に、さらに頻繁に使用されるユースケースは次のとおりです。

この方法で文字列を使用できます:ここ"Hello, #{name}!"#{name}自動的に置き換えられます - これは非常に便利な機能です。構文糖。

ただし%Q、コードに注意してください。これにより、次のコードが文字列に変換され、後で渡さclass_evalれてそこで実行されます。詳しくはこちらをご覧ください。それがなければ、もちろんうまくいきません。

于 2013-07-19T13:11:59.603 に答える
2
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 に送信する前に、文字列補間が正常に機能します。

于 2013-07-19T13:34:38.947 に答える
2

次のコードの class_eval に # が付いているのはなぜですか?

これは文字列補間です。

一例:

x = 12
puts %Q{ the numer is #{x} }
# >>  the numer is 12 

ここに%Q

これは、文字列に複数の引用文字がある場合に、二重引用符で囲まれた文字列の代わりになります。それらの前にバックスラッシュを配置する代わりに。

于 2013-07-19T13:10:21.133 に答える