【问题标题】:block the creation of multiple object of a class阻止创建一个类的多个对象
【发布时间】:2011-10-30 13:19:28
【问题描述】:

如何将任何类的对象限制为一个。我的课看起来像:

class Speaker
  include Mongoid::Document
  field :name, :type => String
end

我只想让一个扬声器实例。一种方法是添加一个验证来检查 Speaker 类已经存在的对象数量。 有红宝石做事的方式吗?

【问题讨论】:

  • 如果你只想要一个扬声器,将它存储在db中是否有意义?我会把它解压到一个配置文件中。
  • @rubish 我需要允许管理员更改值。如果我不将它保存在数据库中,我将如何有效地做到这一点?
  • 我在下面写的验证呢?
  • @Slawosz 我认为这是我现在能做的最好的事情。等我能找到更好的解决方案。

标签: ruby-on-rails ruby ruby-on-rails-3 mongoid


【解决方案1】:

使用Singleton 模块怎么样?

【讨论】:

  • 如何更改值。我也希望这个价值能够持久。
  • 如果是管理员用户更改了值,那么这个答案有代码味道。否则请参阅stackoverflow.com/questions/137975/… 进行冗长的辩论。
【解决方案2】:

在这种情况下,我会编写适当的验证:

validate :only_one

def only_one
   errors.add(:base, "Only one Speaker can exist") if self.count > 0 
end

【讨论】:

  • 如果记录已经存在并且您正在更新它,这将失败。
  • 好点,但你可以写: validate :only_one, :on => :create
  • NoMethodError: undefined method `count` for #<Speaker:0x28f18e1d> - self在验证方法的上下文中是一个实例,所以self.count需要改为Speaker.countself.class.count
【解决方案3】:

我建议使用为存储配置值而定制的类/模块,而不是在普通 ActiveRecord 模型之上滚动您自己的。

我使用带有一些自定义修改的 rails-settings 插件的旧副本(它在 Rails 3 中仍然可以正常工作)。 Github 上还列出了许多变体产品,因此请随意查看并选择。

【讨论】:

    【解决方案4】:

    为什么不提供默认的 Speaker 对象,而只是不提供用于创建或删除的控制器操作?

    似乎是迄今为止最简单的解决方案。

    【讨论】:

      【解决方案5】:

      我看到你正在使用Mongoid

      您请求的功能无法使用mongoid validations

      因此,您需要自己编写。 before_validationsupported callback 和链接的 Speaker.all.count 方法 are available to your model

      class Speaker
        include Mongoid::Document
        field :name, :type => String
        before_validation(:ensure_has_only_one_record, :on => :create)
        def ensure_has_only_one_record
          self.errors.add :base, "There can only be one Speaker." if Speaker.all.count > 0
        end
      end
      

      但是,best practice is to put all key/value settings in a single table.

      【讨论】:

        【解决方案6】:

        使用 Singleton 模块并稍微覆盖它的方法,我相信这是可行的并且它是线程安全的(在 ruby​​ 1.8 上):

        class Speaker 
        
          include Singleton
          include Mongoid::Document
          field :name, :type => String
        
          @@singleton__instance__ = nil
          @@singleton__mutex__ = Mutex.new
        
          def self.instance
            return @@singleton__instance__ if @@singleton__instance__
            @@singleton__mutex__.synchronize {
              return @@singleton__instance__ if @@singleton__instance__
              @@singleton__instance__ = self.first
              @@singleton__instance__ ||= new()
            }
            @@singleton__instance__
          end
        
          def destroy
            @@singleton__mutex__.synchronize {
              super
              @@singleton__instance__ = nil
            }
          end
        
        end
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-15
        • 1970-01-01
        • 2018-08-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多