Rails ActiveRecord:当记录进入特定状态时锁定属性

Gor*_*nor 11 activerecord ruby-on-rails

想知道是否有插件或设置ActiveRecord类的最佳方式,例如,当记录进入"已发布"状态时,某些属性被冻结,以便它们不会被篡改.

Fra*_*eil 15

编辑不应编辑的属性是验证错误:

class Post < ActiveRecord::Base
  validate :lock_down_attributes_when_published

  private

  def lock_down_attributes_when_published
    return unless published?

    message = "must not change when published"
    errors.add(:title, message) if title_changed?
    errors.add(:published_at, message) if published_at_changed?
  end
end
Run Code Online (Sandbox Code Playgroud)

这使用2.2左右引入的ActiveRecord :: Dirty扩展.


Col*_*tin 9

您可以通过将@readonly设置为true(在方法中)来冻结整个AR :: B对象,但这将锁定所有属性.

我建议的方法是定义属性setter方法,在传递给super之前检查当前状态:

class Post < ActiveRecord::Base
  def author=(author)
    super unless self.published?
  end

  def content=(content)
    super unless self.published?
  end
end
Run Code Online (Sandbox Code Playgroud)

[编辑]或者对于大量属性:

class Post < ActiveRecord::Base
  %w(author content comments others).each do |method|
    class_eval <<-"end_eval", binding, __FILE__, __LINE__
      def #{method}=(val)
        super unless self.published?
      end
    end_eval
  end
end
Run Code Online (Sandbox Code Playgroud)

当然我会主张插入一个插件与他人分享,并添加一个很好的DSL访问,如: disable_attributes :author, :content, :comments, :when => :published?