activerecord-batch_touching 1.0.pre.beta3 → 1.0.pre.beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/activerecord/batch_touching.rb +45 -20
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e3ae09116c725e745e467afa1d834b6b2a28bcae4f01d5346e598235bb7d0a8
|
4
|
+
data.tar.gz: 842acced5ccc6df3149f4ae60b2b7f574f1bf04a553a67b54d6832c1501b94ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5339c3f783b5b4e8f667a47437fa26e507353d648fd99f637ea73925c28d07d626c7eeb9a8850552ae4182ebb1d36ae9acb5acbe0e2d42e7b0d9f1664a0d86d7
|
7
|
+
data.tar.gz: bf5025309b66d19d7571ef34a3701eb23d9d8c054b68619bb6ad1f881439b37eb99e2a6fdd67e53dbadccf585ea41ae2703ee09fe10d3a81dd9e422675aa8b56
|
@@ -55,6 +55,28 @@ module ActiveRecord
|
|
55
55
|
end
|
56
56
|
|
57
57
|
class << self
|
58
|
+
# Disable batch touching globally
|
59
|
+
def disable!
|
60
|
+
@disabled = true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Enable batch touching globally
|
64
|
+
def enable!
|
65
|
+
@disabled = false
|
66
|
+
end
|
67
|
+
|
68
|
+
# Disable batch touching for a block
|
69
|
+
def disable
|
70
|
+
Thread.current[:batch_touching_disabled] = false
|
71
|
+
yield
|
72
|
+
ensure
|
73
|
+
Thread.current[:batch_touching_disabled] = false
|
74
|
+
end
|
75
|
+
|
76
|
+
def disabled?
|
77
|
+
Thread.current[:batch_touching_disabled] || @disabled
|
78
|
+
end
|
79
|
+
|
58
80
|
def states
|
59
81
|
Thread.current[:batch_touching_states] ||= []
|
60
82
|
end
|
@@ -66,7 +88,7 @@ module ActiveRecord
|
|
66
88
|
delegate :add_record, to: :current_state
|
67
89
|
|
68
90
|
def batch_touching?
|
69
|
-
states.present?
|
91
|
+
states.present? && !disabled?
|
70
92
|
end
|
71
93
|
|
72
94
|
# Start batching all touches. When done, apply them. (Unless nested.)
|
@@ -91,20 +113,15 @@ module ActiveRecord
|
|
91
113
|
|
92
114
|
# Apply the touches that were batched. We're in a transaction already so there's no need to open one.
|
93
115
|
def apply_touches
|
116
|
+
current_time = ActiveRecord::Base.current_time_from_proper_timezone
|
94
117
|
callbacks_run = Set.new
|
95
118
|
all_states = State.new
|
96
119
|
while current_state.more_records?
|
97
120
|
all_states.merge!(current_state)
|
98
121
|
state_records = current_state.records
|
99
122
|
current_state.clear_records!
|
100
|
-
state_records.each do |
|
101
|
-
|
102
|
-
records.each do |record|
|
103
|
-
unless callbacks_run.include?(record)
|
104
|
-
record._run_touch_callbacks
|
105
|
-
callbacks_run.add(record)
|
106
|
-
end
|
107
|
-
end
|
123
|
+
state_records.each do |(_klass, columns), records|
|
124
|
+
soft_touch_records(columns, records, current_time, callbacks_run)
|
108
125
|
end
|
109
126
|
end
|
110
127
|
|
@@ -112,30 +129,38 @@ module ActiveRecord
|
|
112
129
|
sorted_records = all_states.records.keys.sort_by { |k| k.first.name }.map { |k| [k, all_states.records[k]] }.to_h
|
113
130
|
sorted_records.each do |(klass, columns), records|
|
114
131
|
records.reject!(&:destroyed?)
|
115
|
-
touch_records klass, columns, records if records.present?
|
132
|
+
touch_records klass, columns, records, current_time if records.present?
|
116
133
|
end
|
117
134
|
end
|
118
135
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
columns.each { |column| write_attribute column, current_time }
|
136
|
+
# Only set new timestamp in memory.
|
137
|
+
# Running callbacks also allows us to collect more touches (i.e. touch: true for associations).
|
138
|
+
def soft_touch_records(columns, records, time, callbacks_run)
|
139
|
+
records.each do |record|
|
140
|
+
record.instance_eval do
|
141
|
+
unless destroyed?
|
142
|
+
columns.each { |column| write_attribute column, time }
|
127
143
|
if locking_enabled?
|
128
144
|
self[self.class.locking_column] += 1
|
129
145
|
clear_attribute_change(self.class.locking_column)
|
130
146
|
end
|
131
147
|
clear_attribute_changes(columns)
|
132
148
|
end
|
149
|
+
unless callbacks_run.include?(record)
|
150
|
+
record._run_touch_callbacks
|
151
|
+
callbacks_run.add(record)
|
152
|
+
end
|
133
153
|
end
|
154
|
+
end
|
155
|
+
end
|
134
156
|
|
135
|
-
|
157
|
+
# Touch the specified records--non-empty set of instances of the same class.
|
158
|
+
def touch_records(klass, columns, records, time)
|
159
|
+
if columns.present?
|
160
|
+
sql = columns.map { |column| "#{klass.connection.quote_column_name(column)} = :time" }.join(", ")
|
136
161
|
sql += ", #{klass.locking_column} = #{klass.locking_column} + 1" if klass.locking_enabled?
|
137
162
|
|
138
|
-
klass.unscoped.where(klass.primary_key => records.to_a).update_all([sql,
|
163
|
+
klass.unscoped.where(klass.primary_key => records.to_a).update_all([sql, time: time])
|
139
164
|
end
|
140
165
|
end
|
141
166
|
end
|