Logo

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.