Reputation: 2044
I want to retrieve records form table, initialize some fields, and then update data on memory (not saving to database) after some filter. But this second filter makes a new query to the database, so I can't initialize these fields.
How can I solve this issue?
res=where(code: 0) # (1) retrieve objects from db, as a template
res.each{|r| r.amount=10} # (2) change amount field with 10 in res
Here I expect 10+2 but the result is 0+2: because next line executes query on database, so line (2) it has no effect
res.where("caconana='1221").first.amount+= 2
Possible answer: Is there a better solution than convert 'res' to an array?
res=where(code: 0).to_a
res.each{|r| r.amount=10}
i=res.find_index{|r| r.caconana=='1221'}
res[i]+=2
Thanks to PSKocit I have the solution: find method does not execute query to database
Upvotes: 2
Views: 1459
Reputation: 60058
That each method call on res will cause all the matching ActiveRecords object to be fully constructed anyway. So if you do want them constructed, you might as well use the caconana attributes that got loaded:
res.each {|r| r.amount = 10 }
res.find {|r| r.caconana == 1221 }.amount+=2
(Then you'd need to save
each record to have that committed to the database.)
You can avoid some ActiveRecord object construction with:
where(code: 0).update_all(amount: 10) #One query to the database, no AR objects constructed in memory
Then for the incrementing (this is with AR object construction, but it's just for one record)
obj = where(code: 0).where(caconana: 1221).limit(1).first
obj.amount+=2
#obj.save!
Upvotes: 2