динамические атрибуты рельсов - PullRequest
6 голосов
/ 04 марта 2011

Мне бы хотелось иметь ряд динамических атрибутов для модели пользователя, например, телефон, адрес, почтовый индекс и т. Д., Но я не хотел бы добавлять каждый из них в базу данных. Поэтому я создал отдельную таблицу с именем UserDetails для пар ключ-значение и belongs_to :User.

Есть ли способ как-то сделать что-то динамическое, подобное этому user.phone = "888 888 8888", которое по сути вызывает функцию, которая делает:

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

и затем получите соответствующий получатель:

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

Все это, кроме ряда атрибутов, таких как телефон, почтовый индекс, адрес и т. Д., Без произвольного добавления тонны геттеров и сеттеров?

Ответы [ 2 ]

9 голосов
/ 04 марта 2011

Вы хотите использовать команду делегата:

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

Тогда вы можете свободно делать user.phone = '888 888 888' или обращаться к ней как user.phone.Rails автоматически сгенерирует все методы получения, установки и динамические методы для вас

3 голосов
/ 04 марта 2011

Вы можете использовать некоторое метапрограммирование для установки свойств модели, например: (этот код не тестировался)

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...