Ruby on rails 什么';在Rails应用程序中存储全局应用程序设置的最佳方法是什么?

Ruby on rails 什么';在Rails应用程序中存储全局应用程序设置的最佳方法是什么?,ruby-on-rails,configuration,Ruby On Rails,Configuration,我想处理两种全局配置设置: 用户可以更改的设置,例如是否发送了特定事件的通知邮件 绑定到特定产品版本的设置,如禁用免费版本中的功能,该功能仅在商业版本中可用 存储这些设置的最佳方式是什么?数据库、配置文件、源代码中的硬编码……?以下是我对这类东西的经验:不要覆盖行为 你看,你的第一个想法是这样的: 嗯。。。。有一些系统范围的设置可能被用户(或产品)覆盖,也可能不被用户(或产品)覆盖。嘿我知道!这是作文 从技术上讲,你是对的。因此,您将创建一个设置表,并将所有设置放在其中。然后您将有一个用户设

我想处理两种全局配置设置:

  • 用户可以更改的设置,例如是否发送了特定事件的通知邮件
  • 绑定到特定产品版本的设置,如禁用免费版本中的功能,该功能仅在商业版本中可用

存储这些设置的最佳方式是什么?数据库、配置文件、源代码中的硬编码……?

以下是我对这类东西的经验:不要覆盖行为

你看,你的第一个想法是这样的:

嗯。。。。有一些系统范围的设置可能被用户(或产品)覆盖,也可能不被用户(或产品)覆盖。嘿我知道!这是作文

从技术上讲,你是对的。因此,您将创建一个设置表,并将所有设置放在其中。然后您将有一个用户设置表,如果用户决定,您将覆盖这些设置。它会很好用的

直到将设置添加到一个表而不是另一个表

或者,您会遇到一个错误,即设置X无法在用户或产品级别被覆盖,并且需要5秒以上的时间才能确定设置的确切位置

然后你会意识到:

嘿,我在至少两个不同的地方跟踪所有这些设置。这似乎有点愚蠢

你是对的


所以,是的。继续并将设置保留在数据库中,但要为每个用户或产品清楚地保存它们。在创建行时使用智能默认值,这将使事情变得简单明了。

对于第一种设置,我会将它们保存在用户模型(Users表)中


第二种设置将再次转到数据库。例如,如果一个用户有一个免费帐户,该帐户将以某种方式保存在数据库中。我会有一些助手在申请,例如“免费”或“商业”。这些帮助者可以通过询问当前连接的用户/帐户模型来确定它们是否正确。然后,您可以在应用程序的不同部分使用这些帮助程序来决定是否显示或隐藏某些功能。

对于这两种情况,都可以使用数据库。您将对多个人/产品使用相同的结构,因此这是有意义的。它还允许您在不重新启动服务器的情况下进行更改

我过去就这样处理过: 对于特定于用户的设置,我创建了一个UserSettings模型/表,它与用户有一对一的关系。这样做的原因是,我涉及用户的大多数操作都不需要加载这些设置,因此它们只在需要时包含在数据库的用户加载中

当我这样做时,我通常会对我的列名进行分组,这样我就可以编写基于列名动态创建的帮助程序。这意味着我不必修改视图以合并新设置,除非我添加了一个具有不同命名方案的设置

对于特定于产品的设置,这取决于您的操作方式。有几种方法可以解释你的问题

我的理解是,你想要决定产品级别。用户可以覆盖或禁用用户设置的设置。并可能定义一些特定于产品的设置

我会使用一对多产品来建立关系。设置表将变得简单(产品标识、设置名称、设置默认值、允许用户更改)

这可以做很多事情。它可以让您拥有不同产品的可变设置列表(非常适合于您提供许多不同产品而不是不同的服务访问层的情况)。它还允许您定义用户可以/不能更改的设置,并为该产品类型提供值。可以从管理员视图更改,而无需重新启动应用程序。它也与用户设置无关,如果用户没有产品设置中列出的设置,就不会有问题

缺点是此表中有多个常用设置。我会将每个产品都具有不同值的设置移动到product表中的一个字段中

您还必须编写验证,以确保用户不会更改其产品声称无法更改的设置。您还必须编写助手方法来合并产品和用户端的设置

class标志class Flag < ActiveRecord::Base
  # id, user_id, name, value (serialized probably)

  belongs_to :user

  DEFAULTS = {
    "newsletter" => false
  }

  def self.lookup(user, flag)
    # Please involve memcached here
    case flag
    when "ssl_enabled"
      # Check if user has paid for sufficient access to SSL
      return false
    else
      stored_flag = self.find_by_user_id_and_name(user.id, flag)
      if stored_flag
        return stored_flag.value
      else
        return DEFAULTS[flag]
      end
    end
  end
end

class User < ActiveRecord::Base
  has_many :flags

  def flag(name)
    return Flag.lookup(self, name)
  end
end
#id、用户id、名称、值(可能序列化) 属于:用户 默认值={ “时事通讯”=>错误 } def自我查找(用户、标志) #请在这里联系我 案例标志 “启用ssl_”时 #检查用户是否已支付足够的SSL访问权限 返回错误 其他的 存储的\u flag=self.find\u by\u user\u id\u和\u name(user.id,flag) 如果存储了\u标志 返回存储的\u标志值 其他的 返回默认值[标志] 结束 结束 结束 结束 类用户
对于基于产品版本的内容,您可能无法真正将内容存储在数据库中,因为标志将基于某种授权代码,而不是静态数据。

您已经对他在想什么以及他将如何实现这一点做出了各种假设,但他的实际问题是“存储这些设置的最佳方式是什么?”在这种情况下,你的假设没有任何意义。我认为这不符合“稻草人”的条件,但我不知道还能叫它什么。你必须去规范化才能做到这一点。可能是以序列化设置字段的形式。不一定是坏事,但非规范化总是一种权衡。