问题
i've been searching through similar questions but i still don't get how implement this relationship. I have of course three models :
class Recetum < ActiveRecord::Base
attr_accessible :name, :desc, :duration, :prep, :photo, :topic_id
has_many :manifests
has_many :ingredients, :through => :manifests
end
class Ingredient < ActiveRecord::Base
attr_accessible :kcal, :name, :use, :unity
has_many :manifests
has_many :recetum, :through => :manifests
end
class Manifest < ActiveRecord::Base
attr_accessible :ingredient_id, :quantity, :receta_id
belongs_to :recetum
accepts_nested_attributes_for :ingredient
belongs_to :ingredient
end
Recetum would be a recipe (typo when scaffolding), this recipe may have one or more ingredients (already on the db). So when i create a new Recetum, i need the new recetum to be created and one record inserted in manifest for each ingredient entered by the user.
I would need some help now with views and controllers, how do i create the form for recetum with fields for the ingredients and more important what do i have to modify recetum controller.
Any suggestions or help would be very much appreciated as this part is crucial for my project, thanks in advance.
回答1:
You have a couple options, and mainly they depend on what you want to do in your view. Do you want to display a set number of max_ingredients
or do you want it to be completely dynamic? The dynamic case looks better for the user for sure, but it does make for some more complicated code.
Here is a good RailsCast which explains how to do it dynamically via JavaScript:
http://railscasts.com/episodes/74-complex-forms-part-2
Unfortunately, not everyone runs with JavaScript enabled so you may want to consider doing it the static way.
Firstly, I don't think you need accepts_nested_attributes_for
in your Manifest
model. However, I do think you need it in your Recetum
model. If you're going the static route, you'll probably want to set a reject_if
option too.
accepts_nested_attributes_for :manifests, reject_if: :all_blank
Once you do this, you'll need to add manifests_attributes
to your attr_accessible
.
With the static route, you'll need to prebuild some of the manifests
. In your new
controller you'll want something like this:
max_ingredients.times do
@recetum.manifests.build
end
In your edit
and the error paths of your create
and update
, you may want:
(max_ingredients - @recetum.manifests.count).times do
@recetum.manifests.build
end
Finally, your view will need some way to set the ingredient. I'll assume a select box for now.
f.fields_for :manifests do |mf|
mf.label :ingredient_id, "Ingredient"
mf.collection_select :ingredient_id, Ingredient.all, :id, :name
You'll want to add some sort of formatting through a list or table probably.
Hopefully, that's enough to get you started.
来源:https://stackoverflow.com/questions/14309337/how-to-implement-has-many-through-relationship-in-rails-with-this-example