I expect the following code to work as expected but it gives me a NoMethodError (private method `foo' called for #<MyClass...)
class MyClass
end
my_object = MyClass.new
my_object.instance_variable_set(:@foo, "bar")
MyClass.send("attr_reader", :foo)
puts my_object.foo
The problem is I'm using literally identical code in a larger application and it works exactly as I expect, but when I simplify it to this most basic example it fails.
(I understand there are many other ways to do what I'm doing in Ruby)
Summary. attr_reader and attr_writer in Ruby allow us to access and modify instance variables using the . notation by creating getter and setter methods automatically. These methods allow us to access instance variables from outside the scope of the class definition.
An attribute reader returns the value of an instance variable. Another way of looking at this is that an attribute reader is a method that “exposes” an instance variable. It makes it accessible for others.
In Ruby, object methods are public by default, while data is private. To access and modify data, we use the attr_reader and attr_writer . attr_accessor is a shortcut method when you need both attr_reader and attr_writer .
Use Module#class_eval:
By doing this, the block puts you in the context of MyClass, thus allowing you to call 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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With