3

How do I add a class instance variable, the data for it and a attr_reader at runtime?

class Module
  def additional_data member, data
    self.class.send(:define_method, member)  {
      p "Added method #{member} to #{name}"
    }
  end
end

For example, given this class

class Test
  additional_data :status, 55
end

So that now I can call:

p Test.status # => prints 55

2 Answers 2

4

How about this?

class Object
  def self.additional_data(name, value)
    ivar_name = "@#{name}"

    instance_variable_set(ivar_name, value)

    self.class.send(:define_method, name) do
      instance_variable_get(ivar_name)
    end

    self.class.send(:define_method, "#{name}=") do |new_value|
      instance_variable_set(ivar_name, new_value)
    end
  end
end

class Foo
  additional_data :bar, 'baz'
end

puts Foo.bar # => 'baz'
Foo.bar = 'quux'
puts Foo.bar # => 'quux'

It's pretty self-explanatory, but let me know if you have any questions.

Sign up to request clarification or add additional context in comments.

1 Comment

instead of self.class.send(:define_method, name) ... why not just self.class.define_method(name) ...
4

Module#class_eval is what you want:

def add_status(cls)
  cls.class_eval do
    attr_reader :status
  end
end

add_status(Test)

4 Comments

Thanks for your answer. But I want to be able to add the method status to any class, not just Test. I've updated the question with what I'm trying..
In Ruby everything is an object, if you can do Test.class_eval ... you can do variable.class_eval ... where variable is a class object. I've updated my answer with something that should better match what you want.
...and obviously you can pass in the name of the attribute to the method if you want to.
Instead of class_eval you can also use send, which leads to the somewhat more concise: cls.send(:attr_reader, :status)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.