我正在寻找一种促进用户偏好的机制。如果当前登录的用户没有特定的首选项集,我还希望使用一组“主”首选项。我看到几个与此类似的问题,但它们似乎进入了理论,而不是简单地提出一个高质量的解决方案。
基本上我正在寻找有关管理和存储的输入——模型、控制器等。最初我正在考虑简单地使用一个包含 50 多列的规范化表(用于性能等)。但是,我计划在未来添加各种未知的偏好,除了性能之外,我可以想象多个列会失控。想法?
我正在寻找一种促进用户偏好的机制。如果当前登录的用户没有特定的首选项集,我还希望使用一组“主”首选项。我看到几个与此类似的问题,但它们似乎进入了理论,而不是简单地提出一个高质量的解决方案。
基本上我正在寻找有关管理和存储的输入——模型、控制器等。最初我正在考虑简单地使用一个包含 50 多列的规范化表(用于性能等)。但是,我计划在未来添加各种未知的偏好,除了性能之外,我可以想象多个列会失控。想法?
如果您不需要根据数据库中的个人偏好进行操作或排序,那么您可能需要使用单个位掩码(整数)列。基本上,位掩码是一组表示为二进制数的开/关开关。例如,假设我们有三个偏好:
假设用户有 1 和 3 开启和 2 关闭。使用 1 表示开启,0 表示关闭,其位掩码为:
101
(开关开)
这被存储在数据库中,5
因为101
5 是二进制的。位掩码很容易存储在数据库中(使用单个整数列),并且在您知道运算符后很容易操作(用于将用户的偏好合并到站点默认值中)。Ryan Bates 有一个关于在 Rails 中使用位掩码的很棒的教程:Emmbedded Association。希望这将为您提供您正在寻找的具体示例。
在我看来,定义和使用默认值的最佳方法是在用户偏好表中添加另一行,并将其作为类变量加载到模型中。如果未找到首选项,则覆盖访问器以查找默认值。像这样的东西:
class UserPreference < ActiveRecord::Base
# load default preferences as a class variable
@@defaults ||= find(1).attributes
# redefine accessors or each column to load default if nil
column_names.each do |column|
method_name = "#{column}_with_default".to_sym
send :define_method, method_name do
value = send("#{column_without_default}")
case value
when nil
@@defaults[column]
else
value
end
end
alias_method_chain column, :default
end
...
end
本质上,默认首选项(从第 1 行加载)作为类变量存储在模型中。所有访问器都被重新定义并成为别名方法链的一部分,因此如果返回值为 nil,则返回默认值。我想用 || 而不是大小写,但如果用户将布尔首选项设置为 false,则会导致问题。
编辑:注意我不知道在不重新启动服务器的情况下更新 Rails 应用程序中的默认值的好方法。