Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make increment_counter/decrement_counter accept an amount argument #48128

Merged
merged 1 commit into from May 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,3 +1,11 @@
* Make `increment_counter`/`decrement_counter` accept an amount argument

```ruby
Post.increment_counter(:comments_count, 5, by: 3)
```

*fatkodima*

* Add support for `Array#intersect?` to `ActiveRecord::Relation`.

`Array#intersect?` is only available on Ruby 3.1 or later.
Expand Down
18 changes: 14 additions & 4 deletions activerecord/lib/active_record/counter_cache.rb
Expand Up @@ -126,6 +126,7 @@ def update_counters(id, counters)
#
# * +counter_name+ - The name of the field that should be incremented.
# * +id+ - The id of the object that should be incremented or an array of ids.
# * <tt>:by</tt> - The amount by which to increment the value. Defaults to +1+.
# * <tt>:touch</tt> - Touch timestamp columns when updating.
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
# touch that column or an array of symbols to touch just those ones.
Expand All @@ -136,10 +137,14 @@ def update_counters(id, counters)
# DiscussionBoard.increment_counter(:posts_count, 5)
#
# # Increment the posts_count column for the record with an id of 5
# # by a specific amount.
# DiscussionBoard.increment_counter(:posts_count, 5, by: 3)
#
# # Increment the posts_count column for the record with an id of 5
# # and update the updated_at value.
# DiscussionBoard.increment_counter(:posts_count, 5, touch: true)
def increment_counter(counter_name, id, touch: nil)
update_counters(id, counter_name => 1, touch: touch)
def increment_counter(counter_name, id, by: 1, touch: nil)
update_counters(id, counter_name => by, touch: touch)
end

# Decrement a numeric field by one, via a direct SQL update.
Expand All @@ -151,6 +156,7 @@ def increment_counter(counter_name, id, touch: nil)
#
# * +counter_name+ - The name of the field that should be decremented.
# * +id+ - The id of the object that should be decremented or an array of ids.
# * <tt>:by</tt> - The amount by which to increment the value. Defaults to +1+.
# * <tt>:touch</tt> - Touch timestamp columns when updating.
# Pass +true+ to touch +updated_at+ and/or +updated_on+. Pass a symbol to
# touch that column or an array of symbols to touch just those ones.
Expand All @@ -161,10 +167,14 @@ def increment_counter(counter_name, id, touch: nil)
# DiscussionBoard.decrement_counter(:posts_count, 5)
#
# # Decrement the posts_count column for the record with an id of 5
# by a specific amount.
# DiscussionBoard.decrement_counter(:posts_count, 5, by: 3)
#
# # Decrement the posts_count column for the record with an id of 5
# # and update the updated_at value.
# DiscussionBoard.decrement_counter(:posts_count, 5, touch: true)
def decrement_counter(counter_name, id, touch: nil)
update_counters(id, counter_name => -1, touch: touch)
def decrement_counter(counter_name, id, by: 1, touch: nil)
update_counters(id, counter_name => -by, touch: touch)
end

def counter_cache_column?(name) # :nodoc:
Expand Down
12 changes: 12 additions & 0 deletions activerecord/test/cases/counter_cache_test.rb
Expand Up @@ -40,12 +40,24 @@ class ::SpecialReply < ::Reply
end
end

test "increment counter by specific amount" do
assert_difference "@topic.reload.replies_count", +2 do
Topic.increment_counter(:replies_count, @topic.id, by: 2)
end
end

test "decrement counter" do
assert_difference "@topic.reload.replies_count", -1 do
Topic.decrement_counter(:replies_count, @topic.id)
end
end

test "decrement counter by specific amount" do
assert_difference "@topic.reload.replies_count", -2 do
Topic.decrement_counter(:replies_count, @topic.id, by: 2)
end
end

test "reset counters" do
# throw the count off by 1
Topic.increment_counter(:replies_count, @topic.id)
Expand Down