I'm trying to get a nested form view to update properly. This is however causing problems when the second form has existing data.
I'm using accepts_nested_attributes_for and nested_form_for. The second which only purpose is to dynamically add the form element using js. See github for more
The error I'm getting is:
Couldn't find Muscle with ID=3685340 for Exercise with ID=212831413
I've tried to manually do the updating but my code didnt really work and I'm under the impression that it shouldnt be needed since rails is suppose to take care of it under the hood.
The idea is that: Exercises has many Muscles through Targets And from within the Exercise form I want to be able to add target muscles.
My models:
class Exercise < ActiveRecord::Base
has_many :targets, :dependent => :destroy
has_many :muscles, :through => :targets
accepts_nested_attributes_for :muscles, :reject_if => :all_blank
...
end
class Targ开发者_如何学Goet < ActiveRecord::Base
belongs_to :exercise
accepts_nested_attributes_for :exercise, :update_only => true
belongs_to :muscle
end
class Muscle < ActiveRecord::Base
has_many :targets, :dependent => :destroy
has_many :exercises, :through => :targets
end
My (haml) view:
%p
%b Target(s):
= f.fields_for :muscles do |e|
= e.collection_select :id, Muscle.all, :id, :name
= e.link_to_remove "-remove"
= f.link_to_add "Add target muscle", :muscles
And finally my failing controller:
def update
@exercise = Exercise.find(params[:id])
@exercise.user = current_user
params[:exercise][:muscles_attributes].each { |id, muscle|
target = Target.where(:exercise_id => @exercise.id , :muscle_id => muscle[:id]).first
if target && !(muscle[:_destroy] == "false")
puts "!!>>>>>>>>>>>>>>>>>>destroy target #{target.exercise_id} #{target.muscle_id}"
target.destroy
else
if !target
t = @exercise.targets.build(:muscle_id => muscle[:id])
t.save
end
end
}
respond_to do |format|
if @exercise.update_attributes(params[:exercise])
format.html { redirect_to(@exercise, :notice => 'Exercise was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @exercise.errors, :status => :unprocessable_entity }
end
end
end
Please let me know if I should expose more of my code (the final result will be opensource anyway) ill happily push to github or whatever is requested, thanks in advance.
You could achieve this by manipulating the intermediate table, here targets
.
Insert in your model:
accepts_nested_attributes_for :targets
And in your html, append this line with javascript:
<input name="exercise[targets_attributes][0][muscle_id]" value="the_muscle_id_goes_here" type="hidden">
精彩评论