私はクラス内にインスタンス変数を動的に作成しました:
class Mine
attr_accessor :some_var
def intialize
@some_var = true
end
def my_number num
self.instance_variable_set "@my_#{num}", num
end
end
@my_#{num}
をattr値として作成するにはどうすればよいですか?
例えばこれを実行できるようにしたい:
dude = Mine.new
dude.my_number 1
dude.my_1
=> 1
この回答はクラス空間を汚染しません。たとえば、_mine.my_number 4
_を実行すると、Mine
の他のインスタンスは_my_4
_メソッドを取得できません。クラスの代わりに。
_class Mine
def my_number num
singleton_class.class_eval { attr_accessor "my_#{num}" }
send("my_#{num}=", num)
end
end
a = Mine.new
b = Mine.new
a.my_number 10 #=> 10
a.my_10 #=> 10
b.my_10 #=> NoMethodError
_
これは__send__
。ここに:
class Mine
attr_accessor :some_var
def intialize
@some_var = true
end
def my_number num
self.class.__send__(:attr_accessor, "my_#{num}")
self.__send__("my_#{num}=", num)
end
end
dude = Mine.new
dude.my_number 1
puts dude.my_1
=> 1
簡単です。 my_numberメソッド内で属性リーダーを動的に定義できます。
def my_number num
self.instance_variable_set "@my_#{num}", num
self.class.class_eval do
define_method("my_#{num}") { num }
end
end
それがあなたのために働くかどうか見てください
ここで2つのメソッドに1つの問題があります。インスタンス変数が1つのインスタンスで設定されている場合、自分ではなくself.class
でメソッドを定義しているため、そのアクセサーはすべてのインスタンスで使用できます。
dude = Mine.new
dude.my_number 1
puts dude.my_1
dudette = Mine.new
dudette.my_1 = 2 # works, but probably shouldn't
dudette.my_number 2
dude.my_2 = 3 # works, but probably shouldn't
おそらくあなたがしたいことは、インスタンス変数を持つインスタンスのみを変更することです:
class Mine
# ...
def my_number num
class << self
attr_accessor "my_#{num}"
end
self.send("my_#{num}=", num)
end
end
このように、インスタンス変数は、それが作成されたオブジェクトのアクセサーのみを取得します。また、instance_variable_setを気にしませんでした。なぜなら、もしあなたがアクセサを設定しているなら、それを再利用する方が良いと思うからです。しかし、それはスタイルの呼び出しです。ここで重要なのは、class << self
ではなくself.class
を呼び出すことです。
OpenStructを使用することができます。
require "ostruct"
class Mine < OpenStruct
end
dude = Mine.new
dude.my_number = 1
dude.my_number # => 1
なぜあなたが欲しがるかわからないdude.my_1
1を返す-すでに持っているものを返してくれませんか?
パイルに追加するさらに別のソリューション define_singleton_method
:
class Mine
def my_number num
define_singleton_method("num_#{num}") { num }
end
end
これらすべてのソリューションの1つの副作用は、異なる番号で複数回呼び出すと、オブジェクトに多数のメソッドが作成されることです。
dude = Mine.new
dude.my_number 1
dude.my_number 5
dude.my_1
=> 1
dude.my_5
=> 5
古いメソッドを削除することでこれを修正できます:
class Mine
def my_number num
old_num = @num
if @num
# need to use `old_num` local variable
# instance var scope is different inside `class_eval`
singleton_class.class_eval { remove_method("num_#{old_num}") }
end
@num = num
define_singleton_method("num_#{num}") { @num }
end
end
古いスレッドですが、役に立ちました。ありがとうございます。これがコードDorkus Primeの答えですが、ハッシュのname\valuesからインスタンス変数も取得しています
@cookies = browser.cookies.to_a
@cookies.each do |cookie|
self.class.__send__(:attr_accessor, "#{cookie[:name]}")
self.__send__("#{cookie[:name]}=",cookie[:value])
end