简体   繁体   中英

Setting up has_many through correctly in Rails

Yesterday I asked a question about setting up has_and_belongs_to_many relationships between models in Rails. I eventually got those relationships working, however, I realized that I needed to store additional information in my join table, which means I should be using a has_many through relationship with a join model (I presume?).

I now have a Recipe model, Ingredient model, and an Amounts join model. Each Recipe has many Ingredients and vice versa. And each Ingredient in a recipe has a certain Amount in a certain unit type.

Here is my setup so far:

models/recipe.rb

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

models/ingredient.rb

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

models/amounts.rb

class Amounts < ActiveRecord::Base
  belongs_to :recipes
  belongs_to :ingredients
end

MySQL tables:

$ mysql > show columns from recipes;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     | NULL    |                |
| desc       | text         | NO   |     | NULL    |                |
| image_url  | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

mysql> show columns from ingredients;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

mysql> show columns from amounts;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| recipe_id     | int(11)      | NO   |     | NULL    |                |
| ingredient_id | int(11)      | NO   |     | NULL    |                |
| amount        | int(11)      | NO   |     | NULL    |                |
| units         | varchar(255) | NO   |     | NULL    |                |
| created_at    | datetime     | NO   |     | NULL    |                |
| updated_at    | datetime     | NO   |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+

I think I have the relationships set up correctly...I'm just unsure about how to add to the join model/table correctly and then access those values. For instance, will I be able to call @recipe.ingredients and return all the ingredients associated?

EDIT: I apologize for the confusion over what I am trying to do.

When I was using the has_and_belongs_to_many relationship, I could push to @recipe.ingredients with '<<' and have the join table automatically inserted with the recipe_id and ingredient_id. However, this method doesn't seem to work when using has_many through because of the additional attributes in the join table.

How would I go about creating these associations?

you can read and assign to recipe.ingredients directly and it will automatically write to the join table.

But unlikely you will need it since you need additional info for the amount. You probably will need to update/create recipes with nested attributes for amounts coming from a form.

consider a uniqueness contraint on ingredients per recipe in amount model.

hope this helped

Setting up a has_many :through association is some of that Rails magic. You'll have access to all the methods that the has_many association sets up for both the join table, and the related table. Rails will take care of any associations automatically.

Have a look at the Rails guide here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM