gugguson
gugguson

Reputation: 819

Polymorphic association to either another model or parent model

I have a model in Rails called Recipe. The recipe model contains ingredients. Each ingredient line has an association to Food model or another Recipe. So basicly I want a polymorphic association to Food model and the Recipe model. However when I made the change, the recipe_id in the ingredient class is always null. Is there something obvious wrong in the associations?

class Recipe < ActiveRecord::Base
  has_many :ingredients, :as => :element
end

class Food < ActiveRecord::Base
  has_many :ingredients, :as => :element
  has_many :recipes, :through => :ingredients
end

class Ingredient < ActiveRecord::Base
  belongs_to :element, :polymorphic => true
  belongs_to :recipe
end

So, basically an ingredient line for a recipe can contain another recipe or an element from the food table (and each recipe can contain any number of ingredient lines).

Here is a drawing representing what I want:

Drawing of tables

And here is how the schema looks currently in RubyMine:

Rubymine diagram

The problem is that recipe_id in the ingredient lines (which is the parent table) is null now so the relation has stopped working when I started the implementation of the polymorphic association.

Here are the insert lines when I save a recipe:

  SQL (3.4ms)  INSERT INTO "recipes" ("created_at", "description", "directions", "name", "owner", "recipe_source_type_id", "servings", "source", "time", "updated_at", "visibility") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id"  [["created_at", Sun, 10 Jun 2012 13:43:12 UTC +00:00], ["description", "Þetta er önnur prufuuppskrift"], ["directions", "Já, og leiðbeiningar"], ["name", "Prufuuppskrift II"], ["owner", 1], ["recipe_source_type_id", 1], ["servings", 3], ["source", "aaa"], ["time", 3], ["updated_at", Sun, 10 Jun 2012 13:43:12 UTC +00:00], ["visibility", 0]]
  SQL (0.9ms)  INSERT INTO "ingredients" ("created_at", "description", "element_id", "element_type", "order", "qty", "recipe_id", "unit_type_id", "updated_at", "user_entered_qty") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id"  [["created_at", Sun, 10 Jun 2012 13:43:13 UTC +00:00], ["description", "abc"], ["element_id", 9], ["element_type", "Recipe"], ["order", nil], ["qty", 2.0], ["recipe_id", nil], ["unit_type_id", 1], ["updated_at", Sun, 10 Jun 2012 13:43:13 UTC +00:00], ["user_entered_qty", "2 gramm"]]

Another problem which I will tackle afterwards is that the element_type should be Food instead of recipe in this instance. I'm not sure where to set that.

Upvotes: 2

Views: 917

Answers (1)

Theo Scholiadis
Theo Scholiadis

Reputation: 2396

From what I understand, an ingredient can belong to both a Food and a Recipe. If that is the case, then your polymorphic association Element will take care of that.

It will create 2 fields in your Ingredients table, one called element_type and element_id, where element_type will contain which table it is related to, and element_id will contain the id of the record in the table that element_type refers to.

This makes your belongs_to :recipe redundant. In fact, Rails will populate your "polymorphic fields" for you when you assign an Ingredient to a Recipe, and not populate the recipe_id, because you've told it to populate the polymorphic fields by setting :polymorphic => true.

I hope this explains your dilemma. Keeping what I've told you in mind, watch this RailsCast on Polymorphic Associations, and things should clear up.

Hope I helped.

Upvotes: 2

Related Questions