How to assign multiple attributes to ActiveRecord::Relation array in single step?

Viewed 644

There is a function is rails to assign attributes to a Model ActiveRecord instance(single record) without saving(or updating).

For example:

$> post = Post.last #=> #<Post id: 53, title: 'Alpha', user_id: 39, state: 'published'>
$> post.assign_attributes(state: 'pending') #=> nil
$> post #=> #<Post id: 53, title: 'Alpha', user_id: 39, state: 'pending'>

but post is not saved in db.

Same I want to do with multiple records of ActiveRecord::Relation.

For example:

$> posts = Post.where(state: 'published')
#=> #<ActiveRecord::Relation [#<Post id: 50, title: 'Wonderful', user_id: 39, state: 'published'>, #<Post id: 53, title: 'Alpha', user_id: 39, state: 'published'>]>
$> posts.assign_attributes(state: 'pending') #=> nil
$> posts
#=> #<ActiveRecord::Relation [#<Post id: 50, title: 'Wonderful', user_id: 39, state: 'pending'>, #<Post id: 53, title: 'Alpha', user_id: 39, state: 'pending'>]>
2 Answers

You cannot do mass assignment in rails like this

posts.each {|post| post.assign_attributes(state: 'pending')}

each perform operation and do not change nature for posts. So posts will be ActiveRecord::Relation object.

When you use Post.update_all this is special, because it runs an UPDATE ALL SQL statement in the database. Therefore there's no need to iterate over the collection in memory.

Updating all records in ruby memory, on the other hand, cannot do this; you do need to iterate over them:

posts.each { |post| post.assign_attributes(state: 'pending') }

However, this shouldn't be an issue. I can't think of any scenario where you'd want to update a collection of objects in memory, without also wanting to iterate over them at some point.

Related