I'm trying to follow Ryan Bates RailsCast #196: Nested model form part 1. There're two apparent differences to Ryans version: 1) I'm using built-in scaffolding and not nifty as he's using, and 2) I'm running rails 4 (I don't really know what version Ryans using in his cast, but it's not 4).
So here's what I did
rails new survey2 cd survey2 bundle install rails generate scaffold survey name:string rake db:migrate rails generate model question survey_id:integer content:text rake db:migrate
Then I added the associations to the models like so
class Question < ActiveRecord::Base belongs_to :survey end
and so
class Survey < ActiveRecord::Base has_many :questions accepts_nested_attributes_for :questions end
Then I added the nested view part
<%= form_for(@survey) do |f| %> <!-- Standard rails 4 view stuff --> <div class="field"> <%= f.label :name %><br> <%= f.text_field :name %> </div> <div class="field"> <%= f.fields_for :questions do |builder| %> <div> <%= builder.label :content, "Question" %><br/> <%= builder.text_area :content, :rows => 3 %> </div> <% end %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>
and finally the controller so that 3 questions are created whenever a new survey is instantiated
class SurveysController < ApplicationController before_action :set_survey, only: [:show, :edit, :update, :destroy] # Standard rails 4 index and show # GET /surveys/new def new @survey = Survey.new 3.times { @survey.questions.build } Rails.logger.debug("New method executed") end # GET /surveys/1/edit def edit end # Standard rails 4 create # PATCH/PUT /surveys/1 # PATCH/PUT /surveys/1.json def update respond_to do |format| if @survey.update(survey_params) format.html { redirect_to @survey, notice: 'Survey was successfully updated.' } format.json { head :no_content } else format.html { render action: 'edit' } format.json { render json: @survey.errors, status: :unprocessable_entity } end end end # Standard rails 4 destroy private # Use callbacks to share common setup or constraints between actions. def set_survey @survey = Survey.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def survey_params params.require(:survey).permit(:name, questions_attributes: [:content]) end end
So, creating a new survey with three questions is fine. However, if I try to edit one of the surveys, the original three questions are maintained, while an additional three more are created. So instead of having 3 questions for the edited survey, I now have 6. I added
Rails.logger.debug("New method executed")
to the new method in the controller, and as far as I can tell, it is not executed when I'm doing an edit operation. Can anyone tell me what I'm doing wrong?
Any help is greatly appreciated!
So I figured it out. I had to add :id
to the permitted params in the survey_params
method. It now looks like this:
# Never trust parameters from the scary internet, only allow the white list through. def survey_params params.require(:survey).permit(:name, questions_attributes: [:id, :content]) end
which works perfectly. I'm a RoR newbie, so please take my analysis of this with a grain of salt, but I guess that new id's where generated instead of being passed to the update action. Hope this helps someone else out there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With