While I’m not a complete Ruby/Rails newb, I’m still pretty green and I’m trying to figure out how to structure some model relationships. The simplest example I can think of is the idea of “recipes” for cooking.
A recipe consists of one or more ingredients and the associated quantity of each ingredient. Assume we have a master list in the database of all ingredients. That suggests two simple models:
class Ingredient < ActiveRecord::Base
# ingredient name,
end
class Recipe < ActiveRecord::Base
# recipe name, etc.
end
If we just wanted to associate Recipes with Ingredients, that’s as simpling as adding the appropriate belongs_to and has_many.
But what if we want to associate additional information with that relationship? Each Recipe has one or more Ingredients, but we want to indicate the quantity of the Ingredient.
What is the Rails way to model that? Is it something along the lines of a has_many through?
class Ingredient < ActiveRecord::Base
# ingredient name
belongs_to :recipe_ingredient
end
class RecipeIngredient < ActiveRecord::Base
has_one :ingredient
has_one :recipe
# quantity
end
class Recipe < ActiveRecord::Base
has_many :recipe_ingredients
has_many :ingredients, :through => :recipe_ingredients
end
Recipes and Ingredients have a has and belongs to many relationship, but you want to store additional information for link.
Essentially what you are looking for is a rich join model. But, a has_and_belongs_to_many relationship is not flexible enough to store the additional information you require. Instead you will need to use a has_many :through relatinship.
This is how I would set it up.
recipes columns: instructions
recipe_ingredients columns: recipe_id, ingredient_id, quantity
ingredient columns: name
This will provide a basic representation of what you’re looking to do. You may want to add a validation to RecipeIngredients to ensure that each ingredient is listed once per recipe, and a callback to fold duplicates into one entry.