Search code examples
ruby-on-railshas-manybelongs-to

Rails has_many belongs_to relationships


I've got a pretty basic problem but can't seem to get it to work right.

here's the setup -

class Recipe < ActiveRecord::Base
 has_many :recipeIngredients
 has_many :ingredients :through => :recipeIngredients
end

class Ingredient < ActiveRecord::Base
 has_many :recipeIngredients
 has_many :recipes :through => :recipeIngredients
end

class RecipeIngredients < ActiveRecord::Base
 belongs_to :recipe
 belongs_to :ingredients
end

Each ingredient has an ID and a name, Recipe has an ID and a Title, RecipeIngredients has recipe_id, ingredient_id, amount

When I attempt to render using

@recipe = Recipe.find(params[:id])
render :json => @recipe, :include => :ingredients

I get my ingredients, but can't access the amount or name from RecipeIngredients. - this outputs

{
    "list_items": {
        "id": 1,
        "title": "Foo",
        "description": null,
        "ingredients": [
            {
                "id": 1
            },
            {
                "id": 2
            },
            {
                "id": 3
            },
            {
                "id": 4
            }
        ]
    }
}

How can I make the relationship between ingredients and recipeIngredients so that when calling :ingredients I get something like -

{
 "id":1,
 "name":"foo",
 "amount":"2 oz"
}

thanks!


Solution

  • You didn't define many-to-many according to Rails. The correct solution is (file names should be as described):

    app/models/recipe.rb

    class Recipe < ActiveRecord::Base
      has_many :recipe_ingredients
      has_many :ingredients, :through => :recipe_ingredients
    end
    

    app/models/ingredient.rb

    class Ingredient < ActiveRecord::Base
      has_many :recipe_ingredients
      has_many :recipes, :through => :recipe_ingredients
    end
    

    app/models/recipe_igredient.rb

    class RecipeIngredient < ActiveRecord::Base
      belongs_to :recipe
      belongs_to :ingredient
    end
    

    Also verify, your join table defined, as following:

    db/12345_create_recipe_ingredints.rb

    class CreateRecipeIngredients < ActiveRecord::Migration
      def change
        create_table :recipe_ingredients, id: false do |t|
          t.references :recipe
          t.references :ingredient
        end
        add_index :recipe_ingredients, :recipe_id
        add_index :recipe_ingredients, :ingredient_id
      end
    end
    

    After doing this, make a test in your console:

    recipe = Recipe.first # should contain data
    igredient = Ingredient.first # should contain data
    recipe.ingredients << ingredient
    recipe.inspect
    

    If everything works correctly and recipe.inspect contains ingredient, json should be correct