Rails将模型限制为1记录

时间:2014-03-17 23:10:22

标签: ruby-on-rails activerecord

我正在尝试在我的应用中创建一个用户可以更新某些网站范围属性的部分。一个例子是销售税百分比。尽管这个数量相对稳定,但每隔几年就会发生变化。

目前我已经创建了一个Globals模型,其中包含我想要跟踪的属性。例如,要在需要时访问这些属性,我可以简单地执行类似以下代码段的操作。

(1+ Globals.first.sales_tax) * @item.total

处理不经常更改且在站点范围内应用的变量的最佳方法是什么?如果我使用这种方法有没有办法将模型限制为一个记录?最后但更清醒的问题.......我甚至走在正确的轨道上?

3 个答案:

答案 0 :(得分:2)

好的,所以我之前已经处理过这个问题,作为一种设计模式,它不是理想的IMO做事方式,但它有时是唯一的方法,特别是如果你没有直接的磁盘写访问权限,就像在Heroku上部署一样。这是解决方案。

class Global < ActiveRecord::Base
  validate :only_one

  private

  def only_one
    if Global.count >= 1
      errors.add :base, 'There can only be one global setting/your message here' 
    end
  end
end

如果您有直接磁盘访问权限,则可以创建一个YAML配置文件,您可以在用户编辑配置变量时读取/写入/转储。

例如,您可以在config/locales/globals.yml

中添加yaml文件

当你想编辑它时,你可以写

filepath = "#{Rails.root}/config/locales/globals.yml"
globals = YAML.load(File.read("#{Rails.root}/config/locales/globals.yml"))
globals.merge!({ sales_tax: 0.07 })

File.write(filepath) do |f|
  f.write YAML.dump(globals)
end

有关ruby yaml documentation

的更多信息

您还可以使用JSON,XML或任何您想要的标记语言

答案 1 :(得分:2)

在我看来,你非常接近,但根据你最终得到的数据结构,我会把它改为

(1+ Globals.last.sales_tax) * @item.total

然后构建某种类型的接口:

  1. 允许用户创建一个新的Globals对象(可能复制现有的对象) - 这里的用例是存在一些存档,当这些事情发生变化时,尽管你可能会认为这应该是一个仓库功能(I “我不确定你的项目范围。”
  2. 允许用户使用paper_trail等内容更新现有的Globals对象以跟踪更改(在这种情况下,您可能需要验证,如@Brian Wheeler提供的验证)。
  3. 或者,您可以转动Global对象,而是使用类似kindtype列的内容来描绘不同的值,以便您拥有:

    (1+ Globals.where(kind: 'Colorado Sales Tax').last) * @item.total
    

    仍然构建类似于上述接口的接口。

答案 2 :(得分:0)

您可以创建一个类并将所有常量转储到其中。

例如:

class Global
  @sales_tax = 0.9

  def sales_tax
    @sales_tax
  end
end

并访问它:

  

Global.sales_tax

或者,您可以在此post

的行中定义全局变量