Rails:如何暂时禁用对象的持久性?

时间:2013-07-26 19:46:35

标签: ruby-on-rails ruby

如同,freeze禁用更新对象值(一定程度)的能力。我如何构建一个方法User.disable_persistence,该方法将禁用在该对象和关联对象上创建/保存/更新的能力,这些对象直接调用(User.save)和间接调用(User.children << child)。

是否有宝石或简单的方法,如:

class User < ...
  def disable_persistence
    # magic here (nullify save, and other methods, prevent callbacks etc.)
    class_eval :before_save do 
      errors.add(:base, "Persistence has been disabled for this object")
    end
  end
end

3 个答案:

答案 0 :(得分:2)

如果设置为false,您可以添加before_save过滤器来检查重定向到根网址的布尔字段(例如editable)的值。该块将在调用create/save/update方法之前结束。

答案 1 :(得分:2)

问题似乎很简单。但棘手的部分是它的and indirectly (User.children << child)部分。 当父对象(User)是新记录时,可以轻松处理这个问题。但如果不是那么容易就不那么容易。 这是因为当user#children << child的记录是新记录时,像children这样的语句会保存父记录和user 但事实并非如此。在后一种情况下,它仅保存child。这个问题没有解决 这个项目,至少现在是自动的。开发人员必须首先禁用child对象的持久性 为了在后一种情况下实现这一点。

请参阅author_spec.rb文件。告诉你整个故事是非常有帮助的。

我作为回答您的SOW问题的任务开发的整个项目在这里:https://github.com/pmatsinopoulos/disable_persistence

任何想要为此做出贡献的人都会感到自由。

为了方便读者,这里引用了完成整个技巧的代码:

disable_persistence.rb文件:

module DisablePersistence
  extend ActiveSupport::Concern

  def disable_persistence
    @persistence_disabled = true
  end

  def enable_persistence
    @persistence_disabled = false
  end

  module ClassMethods
    def disable_persistence
      @@class_persistence_disabled = true
    end

    def enable_persistence
      @@class_persistence_disabled = false
    end

    def persistence_disabled?
      @@class_persistence_disabled ||= false
    end

    def persistence_disabled
      persistence_disabled?
    end
  end

  included do
    attr_reader :persistence_disabled
    alias :persistence_disabled? :persistence_disabled

    before_save :can_persist?

    after_initialize do |base|
      base.instance_variable_set(:@persistence_disabled, false)
    end

    def can_persist?
      !persistence_disabled? && !self.class.persistence_disabled?
    end

    protected :can_persist?
  end
end

ActiveRecord::Base.send :include, DisablePersistence

注意:

一个。实例将响应:

  1. #disable_persistence
  2. #enable_persistence
  3. #persistence_disabled?
  4. B中。该课程将回复:

    1. #disable_persistence
    2. #enable_persistence
    3. #persistence_disabled?
    4. ℃。有一个protected before_save方法可以检查实例是否可以持久化。它检查是否启用了实例和类持久性。如果禁用任何,则不允许实例持久。

      d。该功能自动包含在所有ActiveRecord::Base类中。这是上面的最后一行。你可能不希望这样。如果您不希望这样,则必须在您希望使用此功能的所有include DisablePersistence课程上致电ActiveRecord::Base

      电子。在我链接到的rails项目中,我有initializer require个包含此代码的文件。查看config/initializers。否则,您将不得不自己要求。

      一些使用示例(假设作者及其书籍):

      第一个例子:

      author = Author.new
      author.disable_persistence
      author.save # will return false and nothing will be saved
      author.enable_persistence
      author.save # will return true and author will be saved
      

      第二个例子:

      author = Author.new
      author.disable_persistence
      book = Book.new
      author.books << book
      author.save # false and nothing will be saved
      

      第三个例子:

      author = Author.new
      author.save
      book = Book.new
      book.disable_persistence
      author.books << book # nothing will be saved
      

      第四个例子:

      author = Author.new
      author.save
      book = Book.new
      author.disable_persistence
      author.books << book # will be saved indeed, because the book has enabled persistency
      

      第五个例子:

      author = Author.new
      Author.disable_persistence
      author.save # will return false and will not save
      

      我希望以上回答你的问题,或者至少在某种程度上有所帮助。

答案 2 :(得分:1)

您可以创建一个事务并为回滚抛出任何更改的异常。

相关问题