method
increment!
v1.1.6 -
Show latest stable
- Class:
ActiveRecord::Base
increment!(attribute)public
Increments the attribute and saves the record.
3Notes
No concurrency
If you want to handle concurrency, this doesn't work:
a = Article.first
b = Article.first
a.increment!(:view_count)
b.increment!(:view_count)
a.reload.view_count # -> 1
b.reload.view_count # -> 1
Instead, use SQL:
def increment_with_sql!(attribute, by = 1)
raise ArgumentError("Invalid attribute: #{attribute}") unless attribute_names.include?(attribute.to_s)
original_value_sql = "CASE WHEN `#{attribute}` IS NULL THEN 0 ELSE `#{attribute}` END"
self.class.update_all("`#{attribute}` = #{original_value_sql} + #{by.to_i}", "id = #{id}")
reload
end
increment_by_sql for PG
Note, if you're using the code below for incrementing by SQL with a Postgres database, it's not going to like the backticks. Just remove them:
def increment_with_sql!(attribute, by = 1)
raise ArgumentError("Invalid attribute: #{attribute}") unless attribute_names.include?(attribute.to_s)
original_value_sql = "CASE WHEN #{attribute} IS NULL THEN 0 ELSE #{attribute} END"
self.class.update_all("#{attribute} = #{original_value_sql} + #{by.to_i}", "id = #{id}")
reload
end
SQL Injection?
Note that the version of leente and timdorr are probably vulnerable to SQL Injection (through attribute param).
Probably you want to look into with_lock instead of handcrafting SQL.