Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby - dynamically add property to class (at runtime) [duplicate]

I'm looking for a way to add properties to my already defined class at runtime, or better:

class Client
    attr_accessor :login, :password
    def initialize args = {}
        self.login    = args[:login]
        self.password = args[:password]
    end
end

But then, I have this hash

{:swift_bic=>"XXXX", :account_name=>"XXXX", :id=>"123", :iban=>"XXXX"} 

and I want this hash to become part of my client instance like

client = Client.new :login => 'user', :password => 'xxxxx'

then with a miraculous magic

client @@%$%PLIM!!! {:swift_bic=>"XXXX", :account_name=>"XXXX", :id=>"123", :iban=>"XXXX"} 

I would be able to access

client.swift_bic => 'XXXX'
client.account_name => 'XXXX'
client.id => 123

and I also would like to maintain a proper object structure like:

Client.new(:login => 'user', :password => 'xxxxx').inspect
#<Client:0x1033c4818 @password='xxxxx', @login='user'>

after the magic

client.inspect
#<Client:0x1033c4818 @password='xxxxx', @login='user', @swift_bic='XXXX', @account_name='XXXX' @id => '123', @iban => 'XXXX'>

which would give me a very nice and well formatted json after that

Is it possible at all?

I'm getting this hash from a webservice, so I wouldn't know if theres a new property in there, and then I would have to update my app each time they perform an upgrade on their service. So, I'm sort of trying to avoid this :/

Thanks chaps.

:)

like image 766
zanona Avatar asked Jun 25 '10 21:06

zanona


1 Answers

The method_missing approach would work, but if you're going to use the accessors a lot after adding them, you might as well add them as real methods, like this:

class Client
  def add_attrs(attrs)
    attrs.each do |var, value|
      class_eval { attr_accessor var }
      instance_variable_set "@#{var}", value
    end
  end
end

This will make them work like normal instance variables, but restricted to just one client.

like image 150
mckeed Avatar answered Oct 13 '22 00:10

mckeed