Increase/Decrease value with Rails
I worked with credit base system, when user did a search, we will charge them 1 credit. When the search is failed, we will refund them 1 credit. The searches are ran concurrently, so we need to make sure the credit is increased/decreased correctly.
Rails has 2 methods called increment
and decrement
to increase/decrease but it’s only increase/decrease on memory.
But luckily, Rails has increment!
and decrement!
to increase/decrease on database and it works for concurrent requests.
user = User.last
#<User: id: 1, credit: 10>
user.increment(:credit) => no query to database
user.increment!(:credit) => 1 query to database
And there is another method User.increment_counter(:credit, user.id)
also works for concurrent requests.
How 2 these increament!
and increment_counter
work? The answer is very simple and clever.
When Rails generates the query, it will increase value based on the current value in the database.
UPDATE "users" SET "credit" = COALESCE("credit", 0) + $1 WHERE "users"."id" = $2 [["credit", 1], ["id", 1]]
There are a lot of use cases like count views, reviews, login attempts… and Rails has a perfect method for this.