我很好奇是否有宝石或每个模型设置的方式。例如,用户首选项。
我希望每个模型都有默认值(比如一个类属性),但是可以定义(在另一个表上!我不希望我的模型上有可序列化的字段)。
例如:
user = User.find(1)
user.settings.newsletter # => true
UserSetting会有一个模型,其模式为key => string,value => string,type => string(布尔值,日期,字符串等)
更新
这是我最终的解决方案。支持设置的值类型(布尔值,时间等)
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
答案 0 :(得分:1)
我将使用User has_many UserSettings实现此功能,UserSetting是user_id,key和value。 也许有一种方便的方法来访问它们,如下:
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)
答案 1 :(得分: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
显然这可以完成工作,但显然不是很强大,所以你可能会遇到陷阱。