Rails: Has_Many com detalhes extras?
-
21-09-2019 - |
Pergunta
Embora eu não seja um Ruby/Rails Newb completo, ainda sou muito verde e estou tentando descobrir como estruturar alguns relacionamentos modelo. O exemplo mais simples em que consigo pensar é a idéia de "receitas" para cozinhar.
Uma receita consiste em um ou mais ingredientes e a quantidade associada de cada ingrediente. Suponha que tenhamos uma lista mestre no banco de dados de todos os ingredientes. Isso sugere dois modelos simples:
class Ingredient < ActiveRecord::Base
# ingredient name,
end
class Recipe < ActiveRecord::Base
# recipe name, etc.
end
Se quiséssemos apenas associar receitas a ingredientes, isso é tão simplificando quanto adicionar o apropriado belongs_to
e has_many
.
Mas e se quisermos associar informações adicionais a esse relacionamento? Cada Recipe
tem um ou mais Ingredients
, mas queremos indicar a quantidade do Ingredient
.
Qual é a maneira de modelar isso? É algo parecido com um 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
Solução
Receitas e ingredientes têm um e pertence a muitos relacionamentos, mas você deseja armazenar informações adicionais para o link.
Essencialmente, o que você está procurando é um modelo de junção rico. Mas, um relacionamento has_and_belongs_to_many não é flexível o suficiente para armazenar as informações adicionais necessárias. Em vez disso, você precisará usar um Has_Many: através do Relatinship.
É assim que eu o configuraria.
Receitas colunas: instruções
class Recipe < ActiveRecord::Base
has_many :recipe_ingredients
has_many :ingredients, :through => :recipe_ingredients
end
Recipe_ingRedients Colunas: Recipe_Id, Ingredient_Id, Quantidade
class RecipeIngredients < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
end
Colunas de ingredientes: nome
class Ingredient < ActiveRecord::Base
has_many :recipe_ingredients
has_many :recipes, :through => :recipe_ingredients
end
Isso fornecerá uma representação básica do que você deseja fazer. Você pode adicionar uma validação aos RecipeingRedients para garantir que cada ingrediente esteja listado uma vez por receita e um retorno de chamada para dobrar duplicados em uma entrada.
Outras dicas
http://railsbrain.com/api/rails-2.3.2/doc/index.html?a=m001888&name=has_and_belongs_to_many
http://railsbrain.com/api/rails-2.3.2/doc/index.html?a=m001885&name=has_many
Que tal:
- Ingrediente de classe (pertence à receita, tem muitos ingredientes -concursos)
- Receita de classe (possui muitos ingredientes, tem muitos ingredientes -recipeCounts)
- Ingrediente de classe RecipeCount (pertence ao ingrediente, pertence à receita)
Isso não é tanto da maneira que estabelece mais uma relação entre os dados no banco de dados. Não é realmente um "tem e pertence a muitos", porque cada ingrediente possui apenas uma contagem por receita, e cada receita uma contagem por ingrediente .. que é a mesma contagem.