75

In rails 3, using activerecord, is there a single-query way to set the :hidden field to TRUE for all records that meet a condition ... say, for example, :condition => [ "phonenum = ?", some_phone_number ]

If a single query cannot do it, what IS the optimal approach?

Asherah
  • 18,948
  • 5
  • 53
  • 72
jpw
  • 18,697
  • 25
  • 111
  • 187

3 Answers3

88

Use update_all with the optional second parameter for the condition:

Model.update_all({ hidden: true }, { phonenum: some_phone_number})
Dorian
  • 22,759
  • 8
  • 120
  • 116
Dogbert
  • 212,659
  • 41
  • 396
  • 397
  • 2
    What about the case where a value is less than a certain value for ex update_all( { :hidden => true }, { :date_created < a_certain_date }) is this possible? – ctilley79 Oct 20 '12 at 00:59
  • 7
    @ctilley79, I think this should work: `Model.where("date_create < ?", a_certain_date).update_all(hidden: true)` – Dogbert Oct 20 '12 at 09:21
87

The update_all does not allow conditions in rails 3. You can use combination of scope and update_all

Model.where(phonenum: some_phone_number).update_all(hidden: true)

Reference: http://m.onkey.org/active-record-query-interface

Dorian
  • 22,759
  • 8
  • 120
  • 116
Deepak N
  • 2,561
  • 2
  • 30
  • 44
  • 4
    **This is wrong**. The page says "**supplying any option**", per the paragraph just above the method list describing the various options which can go in the `options` hash. This does not include the `conditions` argument on `update_all()`. – Asherah Aug 17 '12 at 05:55
  • I agree he's wrong. according to the API Avatar.update_all ['migrated_at = ?', Time.now.utc], ['migrated_at > ?', 1.week.ago] will set migrated = now where migrated_at is within a week. – ctilley79 Oct 20 '12 at 15:47
  • 4
    As per rails 4 documentation, the above suggested method is indeed the way to go - http://apidock.com/rails/ActiveRecord/Relation/update_all - # Update all books with 'Rails' in their title Book.where('title LIKE ?', '%Rails%').update_all(author: 'David') – JAR.JAR.beans Oct 05 '14 at 12:35
5

If you want to trigger callbacks:

class ActiveRecord::Base
  def self.update_each(updates)
    find_each { |model| model.update(updates) }
  end

  def self.update_each!(updates)
    find_each { |model| model.update!(updates) }
  end
end

Then:

Model.where(phonenum: some_phone_number).update_each(hidden: true)
Dorian
  • 22,759
  • 8
  • 120
  • 116