ruby Rails:如何暂时禁用对象持久化?

vatpfxk5  于 12个月前  发布在  Ruby
关注(0)|答案(4)|浏览(83)

如中所示,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
0md85ypi

0md85ypi1#

问题似乎很简单。不过,棘手的部分是它的and indirectly (User.children << child)部分。当父对象(User)是新记录时,这可以很容易地处理。但如果不是就没那么容易了。这是因为像user#children << child这样的语句在user的记录是新的时保存父记录和children,但在它不是新的时不做同样的事情。在后一种情况下,它只保存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

备注:
A.示例将响应:

  1. #disable_persistence
  2. #enable_persistence
  3. #persistence_disabled?
    B.该类将响应:
  4. #disable_persistence
  5. #enable_persistence
  6. #persistence_disabled?
    C.有一个protectedbefore_save方法可以检查示例是否可以持久化。它检查示例和类持久性是否都已启用。如果禁用了any,则不允许示例持久化。
    该功能自动包含在所有ActiveRecord::Base类中。这是上面的最后一行。你可能不想那样。如果你不想这样做,你必须在所有你想要这个特性的ActiveRecord::Base类上调用include DisablePersistence
    在我链接到的rails项目中,我有一个initializerrequire是包含此代码的文件。查看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

我希望上面的内容能回答你的问题,或者至少对你有帮助。

jrcvhitl

jrcvhitl2#

你可以添加一个before_save过滤器来检查一个boolean字段的值(比如editable),如果设置为false,这个boolean字段会重定向到根url。代码块将在调用create/save/update方法之前结束。

vcudknz3

vcudknz33#

试试user.readonly!

>> u = User.last
=> ...
>> u.readonly!
=> true
>> u.save
User is marked as readonly (ActiveRecord::ReadOnlyRecord)
jgzswidk

jgzswidk4#

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

相关问题