Ruby:如何在类级别存储动态生成的列表,这样列表只计算一次,并且只在调用类时才计算

时间:2014-06-11 21:55:15

标签: ruby-on-rails ruby validation activerecord class-variables

我对某些记录进行了ActiveRecord验证,默认情况下会默默地阻止我的rails应用程序保存具有相同字符串值的多个版本的记录,如下所示:

class Boat < ActiveRecord::Base# not actual class name, but I like boating
   validates :boatname, :uniqueness => true
end

我想为我的模型添加before_validation回调,就像这样...

require 'highline/import' #simplifies command prompt response code
class Boat < ActiveRecord::Base
  validates :boatname

  before_validation do |r|
    pre_existing = Boat.find_by_boatname(r.boatname)
    if pre_existing
      puts "whoa! found a boat that already exists with the name '#{r.boatname}':"
      ap pre_existing #pretty prints the column names and values
      resp = ask("press 'o' to overwrite, 'm' to modify the new boat name so it gets added")
      if resp == "o"
        #..code handling responses
      end
   end

但这对于荒谬的程度而言在计算上是昂贵的。我正在考虑像这样处理它,这将我们带到了我的实际问题:

require 'highline/import' #simplifies command prompt response code
class Boat < ActiveRecord::Base
  validates :boatname
  @@existing_boats ||= all.map(&:boatname)

  before_validation do |r|
    if @@existing_boats.include?(r.boatname)
      puts "whoa! found a boat that already exists with the name '#{r.boatname}':"
      ap pre_existing #pretty prints the column names and values
      resp = ask("press 'o' to overwrite, 'm' to modify the new boat name so it gets added")
      if resp == "o"
        #..code handling responses
      end
   end

这是处理这类事情的最佳方法吗?它是否满足我的条件,即每个ruby / rails实例仅加载一次并且只有在调用该类时?我想也许我必须将all.map(&:boatname)组件放入lambda或proc中,以防止每次初始化rails时加载它,但我不确定是否有必要。

也接受对我的设计方法的一般批评,但这不是问题的目的。

1 个答案:

答案 0 :(得分:1)

你想在这里实施的东西

@@existing_boats ||= all.map(&:boatname)

称为缓存。 基本上,缓存会强制您在缓存数据过期后立即更新。让5艘船保存在数据库内,当用户保存其他10艘船时应该返回什么?将缓存保存在模型内部会强制您使用某些外部计时器解决方案或其他模型回调来更新缓存的值。这可以通过更轻松的方式解决,请查看this stackoverflow questionthis tutorial

我也不确定知道关系数据库中存在重复值所需的时间。你有船名字段的索引吗?该查询不应该花很长时间。

更多相关内容,我不确定这里发生了什么:

resp = ask("press 'o' to overwrite, 'm' to modify the new boat name so it gets added")

MVC模式暗示在模型层内部不可能要求用户输入,因此你根本无法在rails中执行此类操作。