Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails dynamic attributes

I'd like to have a number of dynamic attributes for a User model, e.g., phone, address, zipcode, etc., but I would not like to add each to the database. Therefore I created a separate table called UserDetails for key-value pairs and a belongs_to :User.

Is there a way to somehow do something dynamic like this user.phone = "888 888 8888" which would essentially call a function that does:

UserDetail.create(:user => user, :key => "phone", :val => "888 888 8888")

and then have a matching getter:

def phone  
    UserDetail.find_by_user_id_and_key(user,key).val
end

All of this but for a number of attributes provided like phone, zip, address, etc., without arbitrarily adding a ton of of getters and setters?

like image 934
miketucker Avatar asked Mar 04 '11 13:03

miketucker


2 Answers

You want to use the delegate command:

class User < ActiveRecord:Base
  has_one :user_detail
  delegate :phone, :other, :to => :user_detail
end

Then you can freely do user.phone = '888 888 888' or consult it like user.phone. Rails will automatically generate all the getters, setters and dynamic methods for you

like image 136
Fernando Diaz Garrido Avatar answered Sep 19 '22 01:09

Fernando Diaz Garrido


You could use some meta-programming to set the properties on the model, something like the following: (this code was not tested)

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
like image 34
Dan McClain Avatar answered Sep 22 '22 01:09

Dan McClain