increment!

- 1.0.0 (0)
- 1.1.6 (0)
- 1.2.6 (0)
- 2.0.3 (0)
- 2.1.0 (30)
- 2.2.1 (0)
- 2.3.8 (0)
- 3.0.0
- 3.0.9
- 3.1.0
- 3.2.1
- 3.2.8
- 3.2.13
- 4.0.2
- 4.1.8
- 4.2.1
- 4.2.7
- 4.2.9
- 5.0.0.1
- 5.1.7
- 5.2.3
- 6.0.0
- 6.1.3.1
- 6.1.7.7
- 7.0.0
- 7.1.3.2
- 7.1.3.4
- What's this?
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

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.

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