15

I have a query update deals set count = count + 1. In Rails, when I do this using ActiveRecord, I can think of

Deal.all.each { |deal| deal.update_attribute(:count => (deal.count + 1))}

and this take a lot more SQL queries instead of one query. Is there a better way to do this in Rails (not using the SQL query directly in the Rails app).

rubyprince
  • 17,559
  • 11
  • 64
  • 104
  • Related: http://stackoverflow.com/questions/4912510/rails-3-activerecord-the-best-way-to-mass-update-a-single-field-for-all-the – Dogbert Feb 11 '11 at 09:07

2 Answers2

21
Deal.update_all("count = count + 1")

outputs

UPDATE "deals" SET count = count + 1

And with a conditional:

Deal.where(order_id: 2).update_all("count = count + 1")

outputs

UPDATE "deals" SET count = count + 1 WHERE "deals"."order_id" = 2
Petr Bela
  • 8,493
  • 2
  • 33
  • 37
Evan
  • 7,396
  • 4
  • 32
  • 31
8

Using ActiveRelation update_all Updates all records with details given if they match a set of conditions supplied, limits and order can also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the database. It does not instantiate the involved models and it does not trigger Active Record callbacks.

http://apidock.com/rails/ActiveRecord/Base/update_all/class

Syed Aslam
  • 8,707
  • 5
  • 40
  • 54
  • @noodi Yes, I know that and it is shown in the query I have stated `update deals set count = count + 1`.. What I am asking is how you can achieve it in Rails. Can you please show? – rubyprince Feb 11 '11 at 09:36
  • 1
    @rubyprince you can do, Deal.update_all("count = count + 1"). But, isn't safe. Passing String arguments to update_all is an invitation to SQL injection attacks. – Syed Aslam Feb 11 '11 at 09:46
  • 8
    @Syed Aslam How can an SQL injection occur where you are passing a static string? – cesoid Nov 19 '14 at 01:00