Forum: Ruby on Rails Update multiple records with a list of ids

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D0512595c86d7ecafb12bd23140d3099?d=identicon&s=25 Joel Young (skizzybiz)
on 2005-11-17 02:21
This is a beginner-ish question, I know, but I can't seem to find
example code anywhere that resembles what I'm doing. The line I can't
get working is this:

    @comments = Comment.update @params['comments'].keys, :status =>
status

status has been set to the string 'approve', and
@params['comments'].keys returns a list of valid ids, but when I run the
code, I get this in my logs:

  Comment Load (0.004792)   SELECT * FROM comments WHERE comments.id =
'2' LIMIT 1
  SQL (0.000320)   BEGIN
  Comment Columns (0.000637)   SHOW FIELDS FROM comments
  Comment Update (0.000752)   UPDATE comments SET `date` = '2005-10-30
18:29:11', `comment` = 'something else', `status` = 'moderate',
`user_id` = 1, `post_id` = 1 WHERE id = 2
  SQL (0.000266)   COMMIT

In other words, it's ignoring the ':status => status' argument. I
suspect I'm messing up the syntax, but reading through the
ActiveRecord::Base source doesn't give me any tips on how to do it
properly. Any suggestions?

Joel
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 christopher.k.hall (Guest)
on 2005-11-17 13:39
(Received via mailing list)
here's the source for AR update method:

    # File vendor/rails/activerecord/lib/active_record/base.rb, line 473
473:       def update(id, attributes)
474:         if id.is_a?(Array)
475:           idx = -1
476:           id.collect { |id| idx += 1; update(id, attributes[idx]) }
477:         else
478:           object = find(id)
479:           object.update_attributes(attributes)
480:           object
481:         end
482:       end

if you have id = [1,2,3], and attributes = { :status => "approve" }

the way i read this, update will do:

if id is an array set counter idx = -1, then for each id, increment idx
by 1
and update current id with attributes value at index idx

id is array, idx = -1
id = 1, idx = 0, update(1, attributes[0])
id = 2, idx = 1, update(2, attributes[1])
id = 3, idx = 2, update(3, attributes[2])

which is equivalent to:

id is array, idx = -1
id = 1, idx = 0, update(1, {:status => "approved")
id = 2, idx = 1, update(2, nil)
id = 3, idx = 2, update(3, nil)

which makes sense that nothing is getting updated after the first
record...

so what's happening is that it appears update assumes attributes to be
an
array of hashes matching the size of the id array *IF* id is an array.

so what you want to do is...

statuses = Array.new(@params['comments'].size, { :status => "approved"
})
@comments = Comment.update(@params['comments'].keys, statuses)

see if this works

Chris
A2c85dc5ee81b12e3cc0a6522e8d079d?d=identicon&s=25 christopher.k.hall (Guest)
on 2005-11-17 13:39
(Received via mailing list)
gah, the formatting for the source is messed up

second try...

# Finds the record from the passed +id+, instantly saves it with the
passed
+attributes+ (if the validation permits it),
# and returns it. If the save fail under validations, the unsaved object
is
still returned.
def update(id, attributes)
if id.is_a?(Array)
idx = -1
id.collect { |id| idx += 1; update(id, attributes[idx]) }
else
object = find(id)
object.update_attributes(attributes)
object
end
end
D0512595c86d7ecafb12bd23140d3099?d=identicon&s=25 Joel Young (skizzybiz)
on 2005-11-17 20:23
christopher.k.hall wrote:
> so what you want to do is...
>
> statuses = Array.new(@params['comments'].size, { :status => "approved"
> })
> @comments = Comment.update(@params['comments'].keys, statuses)
>
> see if this works

Thanks, that was the ticket! I actually decided to just loop through it
myself, like so:

    @params['comments'].keys.each { |id| Comment.update id, :status =>
status }

Since this is a comment moderation system with a potentially large
number of comments being approved/denied (especially the latter) at
once, I think I'll change it to update_all with a list of ids. In any
case, thanks for clearing that up! I don't know how I missed the fact
that attributes has to be an array of hashes.

Joel
This topic is locked and can not be replied to.