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



167
168
169
170
171
172
173
174
175
176
# File 'lib/attribute_guard.rb', line 167

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.



181
182
183
# File 'lib/attribute_guard.rb', line 181

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

Parameters:

  • attributes (Array<Symbol, String>)

    the attributes to unlock

Returns:

  • (Object)

    the object itself



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/attribute_guard.rb', line 141

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