Module: AttributeGuard

Extended by:
ActiveSupport::Concern
Defined in:
lib/attribute_guard.rb

Overview

Extension for ActiveRecord models that adds the capability to lock attributes to prevent direct changes to them. This is useful for attributes that should only be changed through specific methods.

Examples:

class User < ActiveRecord::Base
  include AttributeGuard

  lock_attributes :name, :email
end

user = User.create!(name: "Test", email: "test@example")
user.name = "Test 2"
user.save! # => raises ActiveRecord::RecordInvalid

user.unlock_attributes(:name)
user.name = "Test 2"
user.save! # => saves successfully

user.unlock_attributes(:name) do
  user.name = "Test 3"
  user.save! # => saves successfully
end

user.name = "Test 4"
user.save! # => raises ActiveRecord::RecordInvalid

Defined Under Namespace

Modules: ClassMethods, Initializer Classes: LockedAttributeError, LockedAttributesValidator

Instance Method Summary collapse

Instance Method Details

#attribute_locked?(attribute) ⇒ Boolean

Returns true if the given attribute is currently locked.

Parameters:

  • attribute (Symbol, String)

    the attribute to check

Returns:

  • (Boolean)

    whether the attribute is locked



174
175
176
177
178
179
180
181
182
183
# File 'lib/attribute_guard.rb', line 174

def attribute_locked?(attribute)
  return false if new_record?

  attribute = attribute.to_s
  return false unless self.class.send(:locked_attributes).include?(attribute)

  return true if @unlocked_attributes.nil?

  !@unlocked_attributes.include?(attribute.to_s)
end

#clear_unlocked_attributesvoid

This method returns an undefined value.

Clears any unlocked attributes.



188
189
190
# File 'lib/attribute_guard.rb', line 188

def clear_unlocked_attributes
  @unlocked_attributes = nil
end

#unlock_attributes(*attributes) ⇒ Object

Unlocks the given attributes so that they can be changed. If a block is given, the attributes are unlocked only for the duration of the block.

This method returns the object itself so that it can be chained.

Examples:

user.unlock_attributes(:email).update!(email: "user@example.com")

Parameters:

  • attributes (Array<Symbol, String>)

    the attributes to unlock

Returns:

  • (Object)

    the object itself



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/attribute_guard.rb', line 148

def unlock_attributes(*attributes)
  attributes = attributes.flatten.map(&:to_s)
  return self if attributes.empty?

  @unlocked_attributes ||= Set.new

  if block_given?
    save_val = @unlocked_attributes
    begin
      @unlocked_attributes = @unlocked_attributes.dup.merge(attributes)
      yield
    ensure
      @unlocked_attributes = save_val
      clear_unlocked_attributes if @unlocked_attributes.empty?
    end
  else
    @unlocked_attributes = @unlocked_attributes.dup.merge(attributes)
  end

  self
end