2011-11-10 27 views
0

我很好奇,如果有寶石或做每個模型設置的方式。例如,用戶偏好。ActiveRecord實例設置

我想每個模型都有默認值(比如一個類屬性),但可以定義(在另一張桌子上!我不想在我的模型上使用可序列化的字段)。

例如:

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

會有對UserSetting一個模型,其具有鍵=>字符串,值=>串,類型=>字符串(布爾值,日期,串等等的一個模式.. 。)

UPDATE:

這裏是我的解決方案,這到底。支持設置值類型(布爾,時間等)

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 

回答

1

我將與用戶的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

看起來不錯,只需要.try(:value) –

+0

@RobertRoss哎呀,是的。修正了。謝謝。 – MrTheWalrus

+0

如果您對最終結果感興趣,請更新原文。 –

0

has_settings寶石似乎要做到這一點,但很可惜沒有出現得以維持。至少,This fork支持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 

顯然,這幹得不錯,但顯然還不是很強大的,所以你可能會遇到的陷阱。