Настройки экземпляра ActiveRecord - PullRequest
0 голосов
/ 10 ноября 2011

Мне любопытно, есть ли драгоценность или способ настройки для каждой модели.Например, пользовательские настройки.

Я хотел бы иметь значения по умолчанию для каждой модели (скажем, атрибута класса), но определяемые (для другой таблицы! Я не хочу сериализуемого поля в моей модели).

Например:

user = User.find(1)
user.settings.newsletter # => true

Была бы модель для UserSetting, которая имеет схему key => string, value => string, type => string (Boolean, Date, String и т. Д....)

ОБНОВЛЕНИЕ:

Вот мое решение в конце.Поддерживает типы значений для настроек (Boolean, Time и т. Д.)

    def setting(key, whiny=true)
      s = user_settings.where(:key => key).first

      if s
        case s.value_type
        when 'Boolean'
          s.value.to_i == 1
        when 'Time'
          Time.parse(s.value)
        else
          s.value
        end
      else
        if whiny
          raise NameError, "Setting key #{key} does not exist for #{name}."
        else
          nil
        end
      end
    end

Ответы [ 2 ]

1 голос
/ 11 ноября 2011

Я бы реализовал это с User has_many UserSettings, а UserSetting - это user_id, ключ и значение. Может быть, есть удобный метод доступа к ним, например:

class User < ActiveRecord::Base
  has_many :user_settings
  def setting(key)
    user_settings.where(:key => key).first.try(&:value)
  end
end

class UserSetting < ActiveRecord::Base
  belongs_to :user
end

Тогда вы можете пойти

user = User.find(1)
user.setting('newsletter') # => true/false (or nil if that setting doesn't exist)
0 голосов
/ 11 ноября 2011

Похоже, что камень has_settings делает это, но, увы, не поддерживается. Этот форк имеет поддержку Rails 3, по крайней мере.

Если вы не можете найти драгоценный камень, который соответствует вашим потребностям, его довольно просто реализовать самостоятельно с простым отношением has_many и немногоМагия расширения ассоциации, например (непроверенная):

class User < ActiveRecord::Base
  has_many :settings do
    # association extension
    def method_missing name, *args
      key = name.to_s

      # setter
      if key.ends_with? '='
        key.chop!
        new_val = args.first

        setting = find_or_create_by_key key

        setting.update_attribute(:value, new_val) &&
          @settings[key] = new_val                && # KISS cache
          true  # to mirror the semantics of update_attribute

      # getter
      elsif @settings.has_key? name # is it cached?
        @settings[name]

      elsif setting = where(:key => name).select(:value).first
        @settings[name] = setting.value # KISS cache again

      else
        super
      end

    end
  end

end

class Setting < ActiveRecord::Base
  belongs_to :user

  serialize :value # so we don't have to bother with an extra :type attribute
end

class CreateSettings < ActiveRecord::Migration
  def up
    create_table :settings do |t|
      t.references :user
      t.string :key
      t.string :value
    end
  end

  def down
    remove_table :settings
  end
end

Очевидно, что это делает работу, но, очевидно, не очень надежно, поэтому вы можете столкнуться с затруднениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...