increment!
increment!(attribute, by = 1)
public
Wrapper around increment that saves the record. This method differs from its non-bang version in that it passes through the attribute setter. Saving is not subjected to validation checks. Returns true if the record could be saved.
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


