Reputation: 187
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.
Upvotes: 1
Views: 538
Reputation: 10988
You can simply type the following:
recipe_ingredient.ingredient.recipe_unit
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
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.
Upvotes: 1
Reputation: 2963
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
Upvotes: 1
Reputation: 27747
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:
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 the
recipe_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 %>
Upvotes: 1