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



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/attribute_guard.rb', line 133

def attribute_locked?(attribute)
  return false if new_record?

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

  if defined?(@unlocked_attributes)
    !@unlocked_attributes.include?(attribute.to_s)
  else
    true
  end
end

#clear_unlocked_attributesvoid

This method returns an undefined value.

Clears any unlocked attributes.



149
150
151
152
153
# File 'lib/attribute_guard.rb', line 149

def clear_unlocked_attributes
  if defined?(@unlocked_attributes)
    remove_instance_variable(:@unlocked_attributes)
  end
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



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/attribute_guard.rb', line 108

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