How can I add an instance variable to an object after the object was initialized?

I have an instance of a class with data and would like to extend it with some instance variables. Here is what I know:

class A

  attr_accessor :id
  attr_accessor :description

  def initialize(id, description = nil)
    @id          = id
    @description = description
  end
  
  def methode1
    puts "Method 1"
  end  

end

a = A.new(1, 'This is a descriptipn')

I got the instances a from another code, so that i don’t have access to the initialization. I can only continue from here:

a.instance_variable_set(:@my_var_1, '')
a.instance_variable_set(:@my_var_2, [])

This works fine. But if I want to get the value , i have to use the following code:

puts a.instance_variable_get(:@my_var_1)

Unfortunately, the following code does not work.

puts a.my_var_1

This makes me wonder why I can’t access the instance variable in this way, since it is now part of my instance.

Another question: How can I add an element to @my_var_2?

a.my_var_2 << 'a'
# => undefined method `my_var_2' for #<A:0x000001a2ad128b48 @id=1, @description="This is a descriptipn", @my_var_1="Text", @my_var_2=[]>Text
(NoMethodError)

Hi,
an instance variable is accessible inside the instantiated object. But it’s not a method.
Thus you have to add a getter and a setter-method

class A
  def my_var= v
    @my_var = y
  end

  def my_var
      @my_var
  end
end 

to achieve your goal.

This can be done through meta programming

you might checkout dry initializer

f = File.new("/tmp")

module AddP 
  def p=(pv)
     @p = pv
   end
   attr_reader :p
end

f.extend AddP
f.p = 2

puts f.p.to_s

Will print: 2
Alternatively:

f = File.new('/tmp')
f.define_singleton_method(:p=) {|value| @p = value }
f.p = 87
puts f.instance_eval("@p").to_s

Prints 87