counter_culture 3.13.1 → 3.13.3
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/CHANGELOG.md +10 -0
- data/README.md +1 -1
- data/lib/counter_culture/counter.rb +16 -16
- data/lib/counter_culture/reconciler.rb +25 -6
- data/lib/counter_culture/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c24eb92adf8139552bb89de6d5f39f41f1fc46b89a9b23f66309385ab31cb6f
|
|
4
|
+
data.tar.gz: b3ec3a46a8bcaa1520b193a47909d3233c0193958849caac5cbe580acc621316
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd20102f237e5a2a3757567339afb5c60d5ef87e6d97c411a2e51a365749e1e45482a63553d631bf8337cbce997d657c708a34a7bf8a4a7d84b87dfd77d241b8
|
|
7
|
+
data.tar.gz: 533d50714673ce1e209db0e7ebbf29717668783014d3753d15306f6e0705c042a50821602ca948ed1444ec5adc76799c059e5735c5db0f416b6664f4fc414459
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 3.13.3 (June 25, 2026)
|
|
2
|
+
|
|
3
|
+
Bugfixes:
|
|
4
|
+
- Fix `counter_culture_fix_counts` raising a SQL syntax error for counter caches stored in reserved-word columns (e.g. `order`) by quoting identifiers in the reconciler (#434)
|
|
5
|
+
|
|
6
|
+
## 3.13.2 (June 25, 2026)
|
|
7
|
+
|
|
8
|
+
Bugfixes:
|
|
9
|
+
- Fix multi-level counter caches not being updated in memory when creating or destroying records (#432)
|
|
10
|
+
|
|
1
11
|
## 3.13.1 (April 20, 2026)
|
|
2
12
|
|
|
3
13
|
Bugfixes:
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# counter_culture [](https://circleci.com/gh/magnusvk/counter_culture/tree/main)
|
|
2
2
|
|
|
3
3
|
Turbo-charged counter caches for your Rails app. Huge improvements over the Rails standard counter caches:
|
|
4
4
|
|
|
@@ -410,9 +410,7 @@ module CounterCulture
|
|
|
410
410
|
|
|
411
411
|
# update associated object counter attribute
|
|
412
412
|
def assign_to_associated_object(obj, relation, change_counter_column, operator, delta_magnitude)
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
association_object = association_object_for_assign(obj, association_name)
|
|
413
|
+
association_object = association_object_for_assign(obj, relation)
|
|
416
414
|
return if association_object.blank? || association_object.frozen?
|
|
417
415
|
|
|
418
416
|
association_object.assign_attributes(
|
|
@@ -422,21 +420,23 @@ module CounterCulture
|
|
|
422
420
|
association_object_clear_change(association_object, change_counter_column)
|
|
423
421
|
end
|
|
424
422
|
|
|
425
|
-
def association_object_for_assign(obj,
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
#
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
423
|
+
def association_object_for_assign(obj, relation)
|
|
424
|
+
relation = relation.is_a?(Enumerable) ? relation.dup : [relation]
|
|
425
|
+
|
|
426
|
+
while !obj.nil? && relation.size > 0
|
|
427
|
+
cur_relation = relation.shift
|
|
428
|
+
# This isn't an association (e.g. it uses delegate), so we can't update the count this way
|
|
429
|
+
return nil if obj.class.reflect_on_association(cur_relation).nil?
|
|
430
|
+
|
|
431
|
+
if !obj.association(cur_relation).loaded?
|
|
432
|
+
# If the association isn't loaded, no need to update the count
|
|
433
|
+
return nil
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
obj = obj.public_send(cur_relation)
|
|
437
437
|
end
|
|
438
438
|
|
|
439
|
-
obj
|
|
439
|
+
obj
|
|
440
440
|
end
|
|
441
441
|
|
|
442
442
|
def association_object_clear_change(association_object, change_counter_column)
|
|
@@ -108,13 +108,15 @@ module CounterCulture
|
|
|
108
108
|
next unless column_name
|
|
109
109
|
|
|
110
110
|
relation_class_table_name = quote_table_name(relation_class.table_name)
|
|
111
|
+
# quote the cache column so reserved-word/quoting-sensitive names work
|
|
112
|
+
quoted_column_name = quote_column_name(column_name)
|
|
111
113
|
|
|
112
114
|
# select join column and count (from above) as well as cache column ('column_name') for later comparison
|
|
113
115
|
counts_query = scope.select(
|
|
114
116
|
"#{primary_key_select}, " \
|
|
115
117
|
"#{association_primary_key_select}, " \
|
|
116
118
|
"#{count_select} AS count, " \
|
|
117
|
-
"MAX(#{relation_class_table_name}.#{
|
|
119
|
+
"MAX(#{relation_class_table_name}.#{quoted_column_name}) AS #{quoted_column_name}"
|
|
118
120
|
)
|
|
119
121
|
|
|
120
122
|
# we need to join together tables until we get back to the table this class itself lives in
|
|
@@ -155,9 +157,20 @@ module CounterCulture
|
|
|
155
157
|
|
|
156
158
|
track_change(record, column_name, count)
|
|
157
159
|
|
|
158
|
-
updates
|
|
159
|
-
#
|
|
160
|
-
updates
|
|
160
|
+
# Build a Hash of column => value updates and let Rails (Arel) qualify
|
|
161
|
+
# and escape the column names and cast/quote the values, consistent with
|
|
162
|
+
# the Arel-based updates used in Counter (see #425). This updates the
|
|
163
|
+
# actual counter.
|
|
164
|
+
updates = { column_name => count }
|
|
165
|
+
|
|
166
|
+
# Set lock_version = lock_version (no-op) to skip Rails auto-increment,
|
|
167
|
+
# just as Counter does (see #429); a Hash update_all would otherwise
|
|
168
|
+
# bump the optimistic locking column.
|
|
169
|
+
if relation_class.locking_enabled?
|
|
170
|
+
lock_column = relation_class.locking_column
|
|
171
|
+
updates[lock_column] = relation_class.arel_table[lock_column]
|
|
172
|
+
end
|
|
173
|
+
|
|
161
174
|
# and here we update the timestamp, if so desired
|
|
162
175
|
if options[:touch]
|
|
163
176
|
current_time = record.send(:current_time_from_proper_timezone)
|
|
@@ -168,13 +181,13 @@ module CounterCulture
|
|
|
168
181
|
timestamp_columns << options[:touch]
|
|
169
182
|
end
|
|
170
183
|
timestamp_columns.each do |timestamp_column|
|
|
171
|
-
updates
|
|
184
|
+
updates[timestamp_column] = current_time
|
|
172
185
|
end
|
|
173
186
|
end
|
|
174
187
|
|
|
175
188
|
with_writing_db_connection do
|
|
176
189
|
conditions = Array.wrap(relation_class.primary_key).map { |key| [key, record.send(key)] }.to_h
|
|
177
|
-
relation_class.where(conditions).distinct(false).update_all(updates
|
|
190
|
+
relation_class.where(conditions).distinct(false).update_all(updates)
|
|
178
191
|
end
|
|
179
192
|
end
|
|
180
193
|
end
|
|
@@ -351,6 +364,12 @@ module CounterCulture
|
|
|
351
364
|
end
|
|
352
365
|
end
|
|
353
366
|
|
|
367
|
+
def quote_column_name(column_name)
|
|
368
|
+
@connection_handler.call do |connection|
|
|
369
|
+
connection.quote_column_name(column_name)
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
354
373
|
def parameterize(string)
|
|
355
374
|
if ACTIVE_RECORD_VERSION < Gem::Version.new("5.0")
|
|
356
375
|
string.parameterize('_')
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: counter_culture
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.13.
|
|
4
|
+
version: 3.13.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Magnus von Koeller
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|