I have tried a couple other similar posts but am still getting an error.
In the Posts model I have a category_id field. I have the following models:
#Posts model
belongs_to :categories
#Category model
has_many :posts
In the Posts index controller I have:
#categories = #posts.Category.find(:all, :order => 'categoryname')
In the View I have:
<% #posts.each do |post| %>
<tr>
<td><%= post.category_id %></td>
<td><%= #categories.categoryname %></td>
<td><%= link_to 'View', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
</tr>
<% end %>
In the 2nd column I am trying to show the category name ("categoryname") from the Category table instead of the category_id from the posts table. I am getting an error:
undefined method `Category' for #ActiveRecord::Relation:0x3e1a9b0>
I have also tried:
<td><%= post.categories.categoryname %></td>
But get the same error.
As well as:
<td><%= post.category.categoryname %></td>
Any suggestions would be greatly appreciated.
In your model
belongs_to :category
In your view
<td><%= post.category.categoryname %></td>
You can get rid of the #categories = line in your controller
Also, categoryname is probably not the best attribute name for your Category model. Why not just name it name. post.category.name seems a lot better than post.category.categoryname, don't you think?
Okay, a couple things
belongs_to :categories
belongs_to is a singular relationship. You should be putting
belongs_to :category
In this case you need category_id in the posts table. You would get the category by
#post.category.categoryname
Unless a post can have many categories, in which case you'd want
#Post
has_and_belongs_to_many :categories
#Category
has_and_belongs_to_many :posts
In this case you need a join table called categories_posts with two fields category_id and post_id and you would get it by calling
#post.categories.each do |cat|
cat.categoryname
end
There are some other problems with you code, like
#categories = #posts.Category.find(:all, :order => 'categoryname')
Category is a model, not your named relationship, which is probably why you are getting the exception in your application.
You will get the following error
undefined method `categoryname' for nil:NilClass on the line: <%= post.category.categoryname %>
if there are records in your table without a category specified.
In other words, make sure all of your records have a category associated with them
i Noticed that #category in your controller starts with a small letter c, but in your view, it starts with a Capital letter !
In your case, if there is a chance that you can have an empty category_id in posts table (as you mentioned in your comment), you can add
if post.category_id?
so your cell will look like this:
<td><%= post.category.categoryname if post.category_id? %></td>
If post.category_id is null it will just show an empty cell.
Related
I have 3 models as below.
Model for Item
class Item < ApplicationRecord
belongs_to :item_type, :class_name=>ItemType, :foreign_key=>"item_type_id"
end
and Model for Ingredients
class Ingredient < ApplicationRecord
validates_presence_of :ingredient, :message=>"name cannot be blank!"
end
and model for recipe_ingredients
class RecipeIngredient < ApplicationRecord
belongs_to :item, :class_name=>Item, :foreign_key=>"item_id"
belongs_to :ingredient, :class_name=>Ingredient, :foreign_key=>"ingredient_id"
validates_numericality_of :quantity
end
The table for ingredients has following columns
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"ingredient" varchar,
"inventory_unit" varchar,
"recipe_unit" varchar,
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL
The view for index of recipe ingredients is as below. The ingredients are appearing in the view. I want to pull recipe unit from ingredients table for the selected ingredient and display it in the table. I have tried it doing a query. The code is as below.
<p id="notice"><%= notice %></p>
<h1>Recipe Ingredients</h1>
<table>
<thead>
<tr>
<th>Item</th>
<th>Ingredient</th>
<th>Quantity</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #recipe_ingredients.each do |recipe_ingredient| %>
<tr>
<td><%= recipe_ingredient.item %></td>
<td><%= recipe_ingredient.ingredient.ingredient %></td>
<td><%= recipe_ingredient.quantity %></td>
<td><%= Ingredient.select('recipe_unit').where(:id => #ingredient_id) %></td>
<td><%= link_to 'Show', recipe_ingredient %></td>
<td><%= link_to 'Edit', edit_recipe_ingredient_path(recipe_ingredient) %></td>
<td><%= link_to 'Destroy', recipe_ingredient, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Recipe Ingredient', new_recipe_ingredient_path %>
But the output I am getting is as shown in image given below.
You can simply type the following:
recipe_ingredient.ingredient.recipe_unit
Why is this possible?
Since a RecipeIngredient belongs_to an Ingredient, you can access the Ingredient of a RecipeIngredient as if it was any other field like this:
recipe_ingredient.ingredient
Once you have the ingredient, you can pull the recipe_unit directly by typing:
recipe_ingredient.ingredient.recipe_unit
Side note:
You can omit the :class_name and :foreign_key hashes from your associativity rules in your model classes. For example, take this class:
class Student < ActiveRecord::Base
belongs_to Course
end
By convention, rails will associate the Student class with the Course class. Rails will look for a column in the "students" database table labeled "course_id", and if "course_id" exists as a column in the table, Rails will automatically use that field as the foreign key for Student. You can use the :foreign_key => 'some_key' notation when you want to override the default conventions in rails (which isn't recommended unless its strictly necessary).
For more reading on the subject of active record migrations and foreign key associations, you can check out the rails docs.
Ok, it's displaying as it is because you are displaying the whole class, not an actual detail of the instance.
In this case below, you are selecting a whole set of Ingredients (the set contains only one ingredient, but it will always return a set):
Ingredient.select('recipe_unit').where(:id => #ingredient_id)
What you probably want is something like this:
Ingredient.find(#ingredient_id).recipe_unit
The differences:
where always returns a set of items (even if there's just one item in the set) What is returned is not an ingredient, but an Active Relation. To just return one ingredient, you need to use find or first (or a similar such method).
select just tells Rails what to pull out of the db... it doesn't tell the template what to display in the template. It says "only fetch the recipe_unit column from the db" it doesn't say and then output therecipe_unitcolumn - for that you need to actually call the recipe_unit method on the ingredient (as in the example I gave).
Note that you have the same problem with recipe_ingredient.item
What column from an item do you want to display? does it have a name or a description if so - you need to actually call that eg:
<%= recipe_ingredient.item.name %>
First of all, you may omit :class_name and :foreign_key from your models because of convention over configuration - your models are named exactly like classes and foreign keys you list.
As for your question, you need to use yak shaving for that:
recipe_ingredient.ingredient.recipe_unit
I'm attempting to return the specific hospital name associated to a patient but keep getting errors.
Models:
Hospital
has_many :patients
Patients
belong_to :hospital
When rendering my page I call the controller:
def list_patients
#patients = Patient.all
end
In my view I print out each patient and their information:
<% #patients.each do |patient| %>
<table>
<tr>
<td><%= patient.first_name + "," + patient.last_name %></td>
<td><%= patient.ssn %></td>
<td><%= patient.dob %></td>
<td><%= patient.hospital.name%></td>
</tr>
</table>
The above returns an "undefined method for name". If I remove name I can see that a object (<Hospital:0x007fa1d9530138>)
is returned, but I'm unable to then access the specific attributes within the object.
I can return the specific hospital ID, if I do something like:
patient.hospital_id
but am then stuck on how to get to the hospital name.
Is your code equal to the pasted one?
If so, is belongs_to and not belong_to
If you also can't do Hospital.first.patients in the console, make sure you have a hospital_id in you patient model
I have developed rails app with three classes.
class Location < ActiveRecord::Base
has_many :observations
end
class Observation < ActiveRecord::Base
belongs_to :location
has_one :rainfall
has_one :temperature
has_one :winddirection
has_one :windspeed
has_one :dewpoint
end
class Rainfall < ActiveRecord::Base
belongs_to :observation
end
Railfall is related to Observation through an observation_id and Observation is related to Location through a location_id.
If i go to console and type something like:
Location.all.first.observations.first.rainfall.value
it returns me the data in value column of rainfall
However when i want to combine all the info in rails in a table and in my view/location/index.html.erb i put:
<tbody>
<% #locations.each do |location| %>
<tr>
<td><%= location.name %></td>
<% unless #observations = nil %>
<% location.observations.each do |obs| %>
<td><%= obs.name %></td>
<% unless #rainfalls = nil %>
<td><%= obs.rainfalls.value %></td>
<% end %>
<% end %>
I get an error:
undefined method `rainfalls' for Observation:0x00000004219068>
I have spent the last 5 hours trying just about everything i can and am getting a tad frustrated....any ideas?
Note i have a locations controller but observation and rainfall were generated as models, so do not. Am thinking i need to add something to my location controller, just can't work out what, and I am unsure why it returns the correct data in console, just no in app.
Observation.has_one :rainfall, so it should be:
<%= obs.rainfall.value %>
You have one to one relationship, not has_many. Replace
<%= obs.rainfalls.value %>
by
<%= obs.rainfall.value %>
In the Color Index View, the following produces a clickable link that takes me to the Color Show View.
<% #colors.each do |color| %>
<tr>
<td><%= link_to color.color_name, color_path(color) %></td>
in the model, I have:
class Color < ActiveRecord::Base
belongs_to :product
I also have a Product Index View, and I want to create a clickable link to the Color Show View, but I can't make it work.
This does not work (for one thing, color_name is not the primary key in the color table:
<% #products.each do |product| %>
<tr>
<td><%= link_to product.color_name, product.color_name, color_path(color.color_name) %></td>
in the model, I have:
class Product < ActiveRecord::Base
has_many :colors
This is not working and I'm getting an error when I try the Color Index View, something like:
undefined local variable or method color
Any ideas?
Solution:
Here's what ended up working:
<% color_id = Color.find_by_color_name(product.color_name) %>
<td><%= link_to product.color_name, color_path(color_id) %></td>
It could also obviously be done on a single line, but two lines makes the code more readable (I think)
What I don't understand is why someone found it necessary to downgrade the question.
color.color_name is giving you error because you don't have color object on Product Index View.
Try <td><%= link_to product.color_name, product.color_name, color_path(product.color) %></td> if there is one-to-one relationship
Try <td><%= link_to product.color_name, product.color_name, color_path(product.colors.first) %></td> if there is one-to-many relationship
Your Product has_many colors. Therefore, your code should be something like this:
<% #products.each do |product| %>
<tr>
<% product.colors.each do |color| %>
<td><%= link_to color.color_name, color_path(color) %></td>
<% end %>
</tr>
<% end %>
It iterates on the colors of your each product and shows link to their show path.
Caution: Probably subjected to N+1 problem. Above is just supposed to give you direction.
I have a 3 table - users, employees, contacts.
The employees and contacts have a foreign key pointing the the associated user.
Employee belongs_to :user
Contact belongs_to :user
User has many employees, contacts
But, I would like to list the employee name or contact name in the user index view.
Do I need to use a find_by_sql statement?
Thanks,
Dave
You have the belongs_to associations set up already, so you can add the has_one association in your User class for employee and contact, then you can do #user.employee.name or #user.contact.name.
You definitely don't need find_by_sql for this.
In your index view,
<table>
<% #users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.employees.map{ |empl| empl.name }.join(", ") %></td>
<td><%= user.contacts.map{ |contact| contact.name }.join(", ") %></td>
</tr>
<% end %>
</table>
The only down side is it will do a query for all the user's employees and all the user's contacts in the loop for user. If the page loads reasonably fast, code it as above, because that's clearer code.