Ruby - 动态地向类添加属性(在运行时)

zan*_*ona 10 ruby hash properties class dynamic

我正在寻找一种方法在运行时向我已经定义的类添加属性,或者更好:

class Client
    attr_accessor :login, :password
    def initialize args = {}
        self.login    = args[:login]
        self.password = args[:password]
    end
end
Run Code Online (Sandbox Code Playgroud)

但是,我有这个哈希

{:swift_bic=>"XXXX", :account_name=>"XXXX", :id=>"123", :iban=>"XXXX"} 
Run Code Online (Sandbox Code Playgroud)

我希望这个哈希成为我的客户端实例的一部分

client = Client.new :login => 'user', :password => 'xxxxx'
Run Code Online (Sandbox Code Playgroud)

然后带着神奇的魔力

client @@%$%PLIM!!! {:swift_bic=>"XXXX", :account_name=>"XXXX", :id=>"123", :iban=>"XXXX"} 
Run Code Online (Sandbox Code Playgroud)

我可以访问

client.swift_bic => 'XXXX'
client.account_name => 'XXXX'
client.id => 123
Run Code Online (Sandbox Code Playgroud)

我还想保持一个适当的对象结构,如:

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

魔术之后

client.inspect
#<Client:0x1033c4818 @password='xxxxx', @login='user', @swift_bic='XXXX', @account_name='XXXX' @id => '123', @iban => 'XXXX'>
Run Code Online (Sandbox Code Playgroud)

这会给我一个非常好的格式良好的json

有可能吗?

我从网络服务获得这个哈希,所以我不知道那里是否有新的属性,然后每次他们对他们的服务进行升级时我都必须更新我的应用程序.所以,我有点想避免这种情况:/

谢谢你.

:)

mck*_*eed 15

这种method_missing方法可行,但是如果你在添加它们之后要经常使用访问器,你可以将它们添加为真正的方法,如下所示:

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

这将使它们像普通的实例变量一样工作,但仅限于一个client.

  • 默认情况下对我不起作用(我试过1.8.7和1.9.1)我通过在self的singleton类上调用class_eval来实现它.它是完全相同的,除了**第3行**变成:`(class << self; self; end).class_eval {attr_accessor var}`另一种写作方式是`(class << self; self;结束).send:attr_accessor,var` (3认同)