Rails ActiveRecord: Locking down attributes when record enters a particular state

activerecord, ruby-on-rails

Solution

You can freeze an entire AR::B object by setting @readonly to true (in a method), but that will lock out all attributes.

The way I would recommend is by defining attribute setter methods that check for the current state before passing to super:

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

  def content=(content)
    super unless self.published?
  end
end

[EDIT] Or for a large amount of attributes:

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

Which of course I would advocate pulling into a plugin to share with others, and add a nice DSL for accessing like: `disable_attributes :author, :content, :comments, :when => :published?`

Problem

Wondering if there’s a plugin or best way of setting up an ActiveRecord class so that, for example, when a record enter the "published" state, certain attributes are frozen so that they could not be tampered with.

Original source