9

In Ruby, is there a way to dynamically add a instance variable to a class? For Example:

class MyClass

  def initialize
    create_attribute("name")
  end 

  def create_attribute(name)
    attr_accessor name.to_sym
  end

end

o =  MyClass.new
o.name = "Bob"
o.name
0

3 Answers 3

27

One way (there are others) is to use instance_variable_set and instance_variable_get as so:

class Test
    def create_method( name, &block )
        self.class.send( :define_method, name, &block )
    end

    def create_attr( name )
        create_method( "#{name}=".to_sym ) { |val| 
            instance_variable_set( "@" + name, val)
        }

        create_method( name.to_sym ) { 
            instance_variable_get( "@" + name ) 
        }
    end
end

t = Test.new
t.create_attr( "bob" )
t.bob = "hello"
puts t.bob
Sign up to request clarification or add additional context in comments.

2 Comments

I like your solution, it's clean an shows getter and setter. Thanks!
How would you go about turning this into a module, so that you can mix it in with classes that you want this functionality?
1

maybe ,

instance_variable_set(name,value)

is what your want!

eg:

class Mclass
  def show_variables
    puts self.class.instance_variables
  end
end

Mclass.instance_variable_set(:@test,1)
o=Mclass.new
o.show_variables

you know, class is object too.

Comments

0

Made a mess of answering @ericso's comment/question in another comment, so here it is in an answer - a module which I use (based on @ReeseMoore's code) to do this & set instance vars, if necessary:

# adds ability to dynamically create instance vars & attr_accessors
module Attributable
  def create_method(name, &block)
    self.class.send(:define_method, name.to_sym, &block)
  end

  def create_setter(m)
    create_method("#{m}=".to_sym) { |v| instance_variable_set("@#{m}", v) }
  end

  def create_getter(m)
    create_method(m.to_sym) { instance_variable_get("@#{m}") }
  end

  def set_attr(method, value)
    create_setter method
    send "#{method}=".to_sym, value
    create_getter method
  end
end

Comments

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.