Как мне динамически добавить attr_reader - PullRequest
17 голосов
/ 01 апреля 2011

Я ожидаю, что следующий код будет работать как положено, но он дает мне NoMethodError (закрытый метод `foo ', вызванный для #

class MyClass
end

my_object = MyClass.new

my_object.instance_variable_set(:@foo, "bar")
MyClass.send("attr_reader", :foo)

puts my_object.foo

Проблема в том, что я использую буквально идентичный код в большем приложении, и он работает точно так, как я ожидаю, но когда я упрощаю его до этого самого простого примера, он терпит неудачу.

(я понимаю, что есть много других способов сделать то, что я делаю в Ruby)

Ответы [ 5 ]

9 голосов
/ 01 апреля 2011

Использование Модуль # class_eval :

При этом блок помещает вас в контекст MyClass, что позволяет вам вызывать attr_reader

ruby-1.9.2-p136 :028 > my_object.instance_variable_set(:@foo, "bar")
 => "bar" 
ruby-1.9.2-p136 :029 > MyClass.class_eval{attr_reader :foo}
 => nil 
ruby-1.9.2-p136 :030 > my_object.foo
 => "bar" 
3 голосов
/ 01 апреля 2011

Интересная проблема, я нашел, что это решение отлично работает:

MyClass.class_eval("attr_reader :foo")
2 голосов
/ 16 апреля 2015

Предположим на мгновение, что вы хотите создать метод доступа для этого конкретного экземпляра класса (что, как я полагаю, имеет место, поскольку вы работаете с экземпляром.

Вы можете просто открыть экземпляркласс singleton и используйте instance_eval для добавления метода доступа

class MyClass
end
my_instance = MyClass.new
my_instance.singleton_class.instance_eval { attr_accessor :foo }
my_instance.foo = :bar
my_instance.foo # => :bar
1 голос
/ 01 апреля 2011

Ответ @MikeLewis хорош, но почему бы просто не открыть класс заново?

irb(main):001:0> class MyClass; end
#=> nil
irb(main):002:0> m = MyClass.new
#=> #<MyClass:0x2d43ae0>
irb(main):003:0> class MyClass; attr_accessor :foo; end
#=> nil
irb(main):004:0> m.foo = 42
#=> 42
0 голосов
/ 01 апреля 2011

Просто заставьте метод стать общедоступным:

MyClass.send("public", :foo)

Понятия не имею, почему в некоторых случаях это личное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...