Search code examples
rubymetaprogrammingclass-instance-variables

Adding a class instance variable and attr_reader to Ruby class at runtime?


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

Solution

  • 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.