SaaSスタンフォードクラス、 この割り当て のパート5を実行しようとしています
私はこの概念を理解するのに本当に苦労しています、これは私がやろうとしたことです:
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s
attr_reader attr_name
attr_reader attr_name + '_history'
class_eval %Q'{def #{attr_name}(a);#{attr_name}_history.Push(a) ; end;}'
end
end
私はおそらくあらゆる種類の間違ったことをしているでしょう。メタプログラミングに関するTheBook Of Rubyの章を読んでも、まだ理解できません。誰かがこれを理解するのを手伝ってくれませんか?
楽しかったです!!!
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
attr_reader attr_name+"_history"
class_eval %Q"
def #{attr_name}=(value)
if !defined? @#{attr_name}_history
@#{attr_name}_history = [@#{attr_name}]
end
@#{attr_name} = value
@#{attr_name}_history << value
end
"
end
end
class Foo
attr_accessor_with_history :bar
end
class Foo2
attr_accessor_with_history :bar
def initialize()
@bar = 'init'
end
end
f = Foo.new
f.bar = 1
f.bar = nil
f.bar = '2'
f.bar = [1,nil,'2',:three]
f.bar = :three
puts "First bar:", f.bar.inspect, f.bar_history.inspect
puts "Correct?", f.bar_history == [f.class.new.bar, 1, nil, '2', [1,nil,'2',:three], :three] ? "yes" : "no"
old_bar_history = f.bar_history.inspect
f2 = Foo2.new
f2.bar = 'baz'
f2.bar = f2
puts "\nSecond bar:", f2.bar.inspect, f2.bar_history.inspect
puts "Correct?", f2.bar_history == [f2.class.new.bar, 'baz', f2] ? "yes" : "no"
puts "\nIs the old f.bar intact?", f.bar_history.inspect == old_bar_history ? "yes" : "no"
Class_evalで文字列を使用する必要がある唯一の理由は、カスタムセッターを定義するときにattr_name
の-valueを参照できるようにするためです。それ以外の場合は、通常、ブロックをclass_eval
に渡します。
あなたがしたことに関して、あなたは実際に解決策の最前線にいます。それだけです#{attr_name}_history
はコードに存在しません。インスタンス変数を作成し、存在しない場合はnilに設定する必要があります。配列が存在する場合は、すでに配列へのプッシュを処理する必要があります。
これを行うにはいくつかの方法があります。 1つの方法はif defined? @#{attr_name}_history DoStuffHere
#{attr_name}_history
はインスタンス変数であることに注意する必要があるため、以下のクラスの@fooのように、前に@を使用してください。
def #{attr_name}=value
、#{attr_name}=
はメソッド名、value
はパラメーター、def func parameter
と同じ
def #{attr_name}=value
(!defined? @#{attr_name}_history) ? @#{attr_name}_history = [nil, value] : @#{attr_name}_history << value
end