Module: ActiveRecord::DelayTouching

Extended by:
ActiveSupport::Concern
Defined in:
lib/activerecord/delay_touching.rb,
lib/activerecord/delay_touching/state.rb

Defined Under Namespace

Modules: ClassMethods Classes: State

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.applyObject

Apply the touches that were delayed.



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/activerecord/delay_touching.rb', line 62

def self.apply
  begin
    ActiveRecord::Base.transaction do
      state.records_by_attrs_and_class.each do |attr, classes_and_records|
        classes_and_records.each do |klass, records|
          touch_records attr, klass, records
        end
      end
    end
  end while state.more_records?
ensure
  state.clear_records
end

.callObject

Start delaying all touches. When done, apply them. (Unless nested.)



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/activerecord/delay_touching.rb', line 49

def self.call
  state.nesting += 1
  begin
    yield
  ensure
    apply if state.nesting == 1
  end
ensure
  # Decrement nesting even if `apply` raised an error.
  state.nesting -= 1
end

.stateObject



40
41
42
# File 'lib/activerecord/delay_touching.rb', line 40

def self.state
  Thread.current[:delay_touching_state] ||= State.new
end

.touch_records(attr, klass, records) ⇒ Object

Touch the specified records–non-empty set of instances of the same class.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/activerecord/delay_touching.rb', line 77

def self.touch_records(attr, klass, records)
  attributes = records.first.send(:timestamp_attributes_for_update_in_model)
  attributes << attr if attr

  if attributes.present?
    current_time = records.first.send(:current_time_from_proper_timezone)
    changes = {}

    attributes.each do |column|
      column = column.to_s
      changes[column] = current_time
      records.each do |record|
        record.instance_eval do
          write_attribute column, current_time
          @changed_attributes.except!(*changes.keys)
        end
      end
    end

    klass.unscoped.where(klass.primary_key => records).update_all(changes)
  end
  state.updated attr, records
  records.each { |record| record.run_callbacks(:touch) }
end

Instance Method Details

#touch(*names) ⇒ Object

Override ActiveRecord::Base#touch.



9
10
11
12
13
14
15
16
# File 'lib/activerecord/delay_touching.rb', line 9

def touch(*names)
  if self.class.delay_touching? && !try(:no_touching?)
    DelayTouching.add_record(self, *names)
    true
  else
    super
  end
end