Axil
Axil

Reputation: 3311

how rails "update" multiple columns correctly - (updated_at should be updated as well)

I am having trouble updating multiple columns properly with rails activerecords. I want to use something like update which basically gets updated_at updated, but i just cant pass multiple column. I could use update_all but it doesnt update updated_at with the current timestamp.

Here's what i'ved tried:

this doesnt work: (only takes in payment_total but not the rest)

retval = @invoice.update(:payment_total => 20, 
                         :due_amount => 10, 
                         :data => clonedata.to_json)  

:data - this is actually a json field

output:

nothing

this works:

 retval = Invoice.where(:id => @invoice.id).update_all(:payment_total => 20, 
                                                     :due_amount => 10, 
                                                     :data => clonedata.to_json)

output: (notice it doesnt update the "updated_at" field)

SQL (1.1ms) UPDATE "invoices" SET "payment_total" = '30.00', "due_amount" = '86.00', "data" = ‘{“name”:”Test}' WHERE "invoices"."id" = 6

a single param would work:

retval = @invoice.update(:payment_total => 20)

output:

UPDATE "invoices" SET "due_amount" = $1, "updated_at" = $2 WHERE "invoices"."id" = 6
  [["due_amount", "86.0"], ["updated_at", "2014-05-18 03:48:49.718692"]]

now how do i use something similar to update multiple columns while updated_at also gets the current timestamp updated ?

Upvotes: 3

Views: 9116

Answers (3)

Ganesh Arulanantham
Ganesh Arulanantham

Reputation: 136

Updates all, 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 or validations. Values passed to update_all will not go through ActiveRecord's type-casting behavior. It should receive only values that can be passed as-is to the SQL database.

As such, it does not trigger callbacks nor validations - and timestamp update is made in a callback.update_at is a call back

Upvotes: -1

Richard Peck
Richard Peck

Reputation: 76774

When you mention you want to update multiple columns - I presume this would be for a single record?


This line will update a collection response (.where returns a collection rather than single object):

retval = Invoice.where(:id => @invoice.id).update_all(:payment_total => 20, 
                                                     :due_amount => 10, 
                                                     :data => clonedata.to_json)

If you're looking to update a single record, I would use the update method like this:

@invoice = Invoice.update(params[id], payment_total: "20", due_amount: "10", data: clonedata.to_json)

Upvotes: 4

James Mason
James Mason

Reputation: 4296

#update is the method you want for this. If it's not working correctly, that means you're not calling it the way you think you are. Maybe try calling #update! and see if you get an exception raised?

Upvotes: -1

Related Questions