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: 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



143
144
145
146
147
148
149
150
151
152
# File 'lib/attribute_guard.rb', line 143

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.



157
158
159
# File 'lib/attribute_guard.rb', line 157

def clear_unlocked_attributes
  @unlocked_attributes = nil
end

#unlock_attributes(*attributes) ⇒ ActiveRecord::Base

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: "[email protected]")

Parameters:

  • attributes (Array<Symbol, String>)

    the attributes to unlock

Returns:

  • (ActiveRecord::Base)

    the object itself



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/attribute_guard.rb', line 117

def unlock_attributes(*attributes)
  attributes = attributes.flatten.map(&:to_s)
  return 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.merge(attributes)
  end

  self
end