I have an index of users where I display the user name, location of user and a field called categories, which can range from zero to many items. I'm having trouble getting the categories to display properly. Here are my details:
User
has_many :user_categories
has_many :categories, :through => :user_categories
Categories
has_many :user_categories
has_many :users, :through => :user_categories
User_categories
belongs_to :user
belongs_to :category
In my user_categories table, there are three columns: id, user_id, category_id.
In my categories table, there are two columns: id and name.
In my user/index view, I have the following:
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%=h user.state %>
<%=h user.categories %> ## This line is the problem
<% end %>
Where I've indicated the problem with my comment directly above, I've tried multiple variations, but somehow I'm missing it. Here are the variations that I've tried, and the results that they produce. Note that for testing, user #2 is the only one with a category that should display.
<%=h user.categories %>
displays: #<Category:0x3f40634>
Log shows:
UserCategory Load (0.4ms) SELECT * FROM "user_categories" WHERE ("user_categories".user_id = 2)
Category Load (0.4ms) SELECT "categories".* FROM "categories" INNER JOIN "user_categories" ON "categories".id = "user_categories".category_id WHERE (("user_categories".user_id = 2))
<%=h user.categories.name %> <-- Here I added .name at the end of the call
displays: category
log shows: App does not do a category load.
<%=h user.user_categories %>
displays: #<UserCategory:0x3e4d1a0>
log shows: UserCategory Load (0.4ms) SELECT * FROM "user_categories" WHERE ("user_categories"."user_id" = 2) AND ("user_categories".user_id = 2) LIMIT 1
Does not do a category load.
<%=h user.user_categories.find_by_user_id(user.id) %>
produces same results as above.
Based on this, I think that <%=h user.categories %> is the one that makes the most sense, but I've tried every variation that I can think of and they all throw exceptions.
The model definitions look correct. You may want to check your database to ensure you've used proper conventions for your ids. I was a concerned that you tried to display all categories in the "problem line". Try looping over them:
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%=h user.state %>
<%=user.categories.each do |c| %>
<%h c.name%>
<%end%>
<% end %>
The problem you were having is that in all three cases, you were attempting to display or operate on a collection of ActiveRecord objects. <%= h user.categories %> and <%= h user.user_categories %> will display the results of calling to_s on the collection, which gives the output (#<Category:0x3f40634> or #<UserCategory:0x3e4d1a0>) you noted. <%= h user.categories.name %> will display the result of calling name on the categories association.
jrhicks' answer works because he iterated over the categories and printed out the name of each one. See http://guides.rubyonrails.org/getting_started.html#hooking-comments-to-posts for a similar example - in that case, they iterate over a post's comments.
Related
<% Schedule.all.each do |schedule| %>
<%= link_to schedule.county, events_path(County: schedule.county) %>
Displays duplicates in the Schedule table
I've tried all below without luck in displaying no duplicates.
<% Schedule.all.each.uniq do |schedule| %>
<% Schedule.distinct.pluck(:county) do |schedule| %>
<% Schedule.distinct.each.pluck(:county) do |schedule| %>
They display nothing for some reason.
Edit:
Associations --
Event has_many :schedules, inverse_of: :event
Schedule belongs_to :event
So the original each block does bring in what I want but grabs the county for each schedule in the database. This results in duplicate county listings. I'm trying to remove these duplicates which I presumed was simple enough by adding a uniq method to the statement but looks like it requires joins. Thanks.
It depends on the association between schedule and country model. Assuming Schedule belongs to country
<% Schedule.joins(country).select(:country).distinct.each do |schedule| %>
<%= link_to schedule.county, events_path(County: schedule.county) %>
<% end %>
<% Schedule.select(:county).distinct.each do |schedule| %>
So looks like I didn't need a join. It was more just a select and then use distinct method which works. Thanks #Tacyons for putting me in the right direction.
I have three tables: illness, symptom and a secondary table to link the other two on a has_many through: relationship.
I wish to implement a system where users type in their symptoms and receive a list of possible illnesses.
Using the code below I can use find(1,2), for example, to show all illnesses that have symptoms 1 and 2 simultaneously. However, I want these two constants to be user-supplied data fed through a form. I'm somewhat new to RoR so I don't know how to do this.
symptoms = Symptom.find(params[:symptom_ids]) # symptom_ids is an array of ids
illnesses = Illness.joins(illness_symptoms: :symptom)
.where("symptoms.id in (?)", symptoms)
.group("illnesses.id")
.having("count(illnesses.id) >= ?", symptoms.length)
In the model:
scope :with_symptoms, -> (symptoms) { joins(illness_symptoms: :symptom)
.where("symptoms.id in (?)", symptoms)
.group("illnesses.id")
.having("count(illnesses.id) >= ?", symptoms.length) }
I use these with Illness.with_symptoms(Symptom.find(1,2)) (I'm looking for a way to replace 1,2 with user-supplied data).
You can do something like this in a form:
<% form_tag some_path do %>
<% #symptoms.each do |symptom| %>
<%= label_tag do %>
<%= check_box_tag "symptom_ids[]", symptom.id %>
<%= symptom.name %>
<% end %>
<% end %>
<% end %>
User will be able to use checkboxes to choose symptoms.
I found it difficult to title this question. It is easier if you see the situation:
by having this in my view
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe_id %>
<% end %>
I am given a list of recipe id's (3 of them) that are in the scrapbook_entries database table.
358 358 341
What I want to do is use these ID's and search the recipe table for all the information linked to them.
E.g. Display #recipe.name with ID 358.
Is there an easy way to do this in the view? Let me know if I am not making sense
If I understand you well, you can immediately put something like
= d.recipe.name
Behind the scenes, this will use your recipe id to look up the correct record, then take the name atttribute of this record
Try this:
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe_id %>
<%= d.recipe ? d.recipe.name : '' %>
<% end %>
If you have the relationship defined on the ScrapbookEntry model you can get the recipe instance and access any of its attributes.
class ScrapbookEntry < ActiveRecord::Base
belongs_to :recipe
end
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe.name %>
<% end %>
you can add a delegate in your scrabook_entry
delegate :name, :to => :recipe
than in your view
d.name
I have something like
<% #users.each do |u| %>
...
<% #interests.each do |i| %>
<% if i joins u in interests_users %> <-- That is not working that way! = Problem
...
<% i.id %>
...
<% end %>
<% end %>
...
<% end %>
I need to output each interest-id that joins users in interests_users for every user. But i cannot use a sql query for each user, because that would be too much for the server, so i query the whole interests table and want to filter it in the view.
Anyone got a simple solution for that?
You're thinking about this too view-centric - this is a data issue, so the model(s) should take care of it.
I'm guessing you have an n-m relationship between users and interests, with the interests-users join table in the middle. The models should define that relationship something like this:
class User < ActiveRecord::Base
has_and_belongs_to_many :interests
end
class Interest ...
has_and_belongs_to_many :users
end
This is with has_and_belongs_to_many (HABTM). The models then already take care of "selecting" which interests are "on" each user, simply query them with user_instance.interests, i.e. do
<% #users.each do |u| %>
...
<% u.interests.each do |i| %>
If that generates a query for interests for each user, you can eager load the data when getting the users:
#users = User.includes(:interests).all
Edit:
Oh yeah and if you want to list all interests and mark those a user has associated, something like this should work:
#interests.each do |interest|
if u.interests.include?(interest) ...
I have a ruby on rails application and i have two models posts and category. Category has_many :posts and Post belongs_to :category. Now how can i display the last post item of each category. i.e retrieving the last post in each category.
In your view something like:
<% #categories.each do |category| %>
<p><%= category.posts.last %></p>
<% end %>
the example above will order the records by id but you might want to order the result by "created_at" field (in case you have it):
<%= category.posts.order('created_at desc').last %>