I wanted to build a basic cookbook. With a Recipes habtm Ingredients Relation.
My first attempt was like this.
class Recipe < ActiveRecord::Base
# title, description
has_many :recipe_ingredients
end
class Ingredient < ActiveRecord::Base
# name, unit
has_many :recipe_ingredients
has_many :recipes, :through => :recipe_ingredients
end
class RecipeIngredient < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
attr_accessible :amount
end
And created the Relation by Hand
RecipeIngredient.create(:recipe_id => 1, :ingredient_id => 2, :amount => 100)
recipe.recipe_ingredients.amout
recipe.recipe_ingredients.ingredient.unit
recipe.recipe_ingredients.ingredient.name
This feels ugly. But I don't know any other solution.
Looks fine to me, as a schema/approach. I think it might just feel ugly because your choice of class name leads you to type "recipe.recipe_ingredients.ingredient" a lot. To me, an 'ingredient' is the food/liquid/whatever AS IT IS USED IN THE RECIPE, so the join table should be called 'ingredients'. Each ingredient has a quantity and links to a 'product' or an 'item' or something similar.
I would rename it thus:
Recipe
has_many :ingredients
has_many :items, :through => :ingredients
Ingredient
#fields - recipe_id, item_id, quantity(string)
belongs_to :recipe
belongs_to :item
Item
has_many :ingredients
has_many :recipes, :through => :ingredients
Now on your view page you can say
<h2><%= recipe.name %></h2>
<dl>
<% @recipe.ingredients.each do |ingredient| %>
<dt><%= ingredient.item.name %></dt>
<dd><%= ingredient.quantity %></dd>
<% end %>
</dl>