rails动态属性

mik*_*ker 6 activerecord ruby-on-rails ruby-on-rails-3

我想为用户模型提供许多动态属性,例如电话,地址,邮政编码等,但我不想将每个属性添加到数据库中.因此,我创建了一个单独的表,称为UserDetails键值对和a belongs_to :User.

有没有办法以某种方式做一些像这样动态的东西user.phone = "888 888 8888"本质上会调用一个函数:

UserDetail.create(:user => user, :key => "phone", :val => "888 888 8888")
Run Code Online (Sandbox Code Playgroud)

然后有一个匹配的getter:

def phone  
    UserDetail.find_by_user_id_and_key(user,key).val
end
Run Code Online (Sandbox Code Playgroud)

所有这一切,但提供了许多属性,如电话,邮编,地址等,而不是随意添加大量的getter和setter?

Fer*_*ido 9

您想使用delegate命令:

class User < ActiveRecord:Base
  has_one :user_detail
  delegate :phone, :other, :to => :user_detail
end
Run Code Online (Sandbox Code Playgroud)

然后你可以自由地做user.phone = '888 888 888'或咨询它user.phone.Rails会自动为您生成所有getter,setter和动态方法


Dan*_*ain 3

您可以使用一些元编程来设置模型的属性,如下所示:(此代码未经测试)

class User < ActiveRecord:Base
  define_property "phone"
  define_property "other"
  #etc, you get the idea


  def self.define_property(name)
    define_method(name.to_sym) do
      UserDetail.find_by_user_id_and_key(id,name).val
    end
    define_method("#{name}=".to_sym) do |value|
      existing_property = UserDetail.find_by_user_id_and_key(id,name)
      if(existing_property)
        existing_property.val = value
        existing_property.save
      else
        new_prop = UserDetail.new
        new_prop.user_id = id
        new_prop.key = name
        new_prop.val = value
        new_prop.save
      end
    end
  end
Run Code Online (Sandbox Code Playgroud)