Reputation: 178
I'm not sure if this is just a lacking of the Rails language, or if I am searching all the wrong things here on Stack Overflow, but I cannot find out how to add an attribute to each record in an array.
Here is an example of what I'm trying to do:
@news_stories.each do |individual_news_story|
@user_for_record = User.where(:id => individual_news_story[:user_id]).pluck('name', 'profile_image_url');
individual_news_story.attributes(:author_name) = @user_for_record[0][0]
individual_news_story.attributes(:author_avatar) = @user_for_record[0][1]
end
Any ideas?
Upvotes: 2
Views: 3875
Reputation: 533
It looks like you're trying to cache the name and avatar of the user on the NewsStory model, in which case, what you want is this:
@news_stories.each do |individual_news_story|
user_for_record = User.find(individual_news_story.user_id)
individual_news_story.author_name = user_for_record.name
individual_news_story.author_avatar = user_for_record.profile_image_url
end
A couple of notes.
I've used find
instead of where
. find
returns a single record identified by it's primary key (id); where returns an array of records. There are definitely more efficient ways to do this -- eager-loading, for one -- but since you're just starting out, I think it's more important to learn the basics before you dig into the advanced stuff to make things more performant.
I've gotten rid of the pluck
call, because here again, you're just learning and pluck
is a performance optimization useful when you're working with large amounts of data, and if that's what you're doing then activerecord has a batch api you should look into.
I've changed @user_for_record
to user_for_record
. The @
denote instance variables in ruby. Instance variables are shared and accessible from any instance method in an instance of a class. In this case, all you need is a local variable.
Upvotes: 0
Reputation: 5967
If the NewsStory
model (or whatever its name is) has a belongs_to
relationship to User
, then you don't have to do any of this. You can access the attributes of the associated User
directly:
@news_stories.each do |news_story|
news_story.user.name # gives you the name of the associated user
news_story.user.profile_image_url # same for the avatar
end
To avoid an N+1 query, you can preload the associated user record for every news story at once by using includes
in the NewsStory
query:
NewsStory.includes(:user)... # rest of the query
If you do this, you won't need the @user_for_record
query — Rails will do the heavy lifting for you, and you could even see a performance improvement, thanks to not issuing a separate pluck
query for every single news story in the collection.
If you need to have those extra attributes there regardless:
You can select them as extra attributes in your NewsStory
query:
NewsStory.
includes(:user).
joins(:user).
select([
NewsStory.arel_table[Arel.star],
User.arel_table[:name].as("author_name"),
User.arel_table[:profile_image_url].as("author_avatar"),
]).
where(...) # rest of the query
Upvotes: 3