Why would my form submit only one model's data

2019-08-21 01:06发布

问题:

I have a form that is intended to submit two models, the first model has_one of the other model, Student_Detail.

Many users on here have helped me with some errors that I encountered already, and now my form submits successfully, but only submits the primary model, Participant.

I've submitted the form a few times and it stores all information that is a direct attribute of the Participant model. In active admin the Participant model data populates, but no Student_Detail records exist.

In the console, Student_Detail data is non-existent.

Form:

    <%= form_for @participant, url: {action: "create"} do |f| %>

                    <%= f.label :first_name, 'First:' %>
                    <%= f.text_field :first_name %>
                    <%= f.label :last_name, 'Last:' %>
                    <%= f.text_field :last_name %>
                    <%= f.label :gender, 'Sex:' %>                       
                    <%= f.select :gender, ['Male', 'Female'] %>
                    <br>
                    <br>
                    <%= f.label :birthdate, 'Birthdate:' %>
                    <%= f.date_field :birthdate %>
                    <%= f.label :email, 'Email:' %>
                    <%= f.text_field :email %>
                    <%= f.label :phone, 'Phone:' %>
                    <%= f.text_field :phone %>

                    <%= f.label :street_name, 'Street Number & Name:' %>
                    <%= f.text_field :street_name %>
                    <%= f.label :city, 'City:' %>
                    <%= f.text_field :city %>
                    <%= f.label :state, 'State:' %>
                    <%= f.text_field :state %>
                    <%= f.label :zip, 'Zip:' %>
                    <%= f.text_field :zip %>
            <!--        <%= f.label :role, 'Role:' %>
                    <%= f.select :role, ['Reader'] %> -->
                    <br>
                    <br>

         <%= f.fields_for @participant.student_detail do |student_detail_field| %>
                    <%= student_detail_field.label :nationality, 'Nationality:' %>  
                    <%= student_detail_field.text_field :nationality %>
                    <%= student_detail_field.label :religion, 'Religion:' %>
                    <%= student_detail_field.text_field  :religion  %>

                    <%= student_detail_field.label :need_ride, 'Do you need help getting to the church building?' %>
                    <%= student_detail_field.select :need_ride, ['Yes','No'] %> 
                    <br>
                    <br>
                    <%= student_detail_field.label :has_spouse, 'Marital Status:' %>
                    <%= student_detail_field.select :has_spouse, ['married', 'single'] %>
                    <br>
                    <br>
                    <%= student_detail_field.label :spouse_name, "If married, spouse's name:" %>
                    <%= student_detail_field.text_field  :spouse_name %>
                    <%= student_detail_field.label :english_level, 'English Level:' %>
                    <%= student_detail_field.select :english_level, ['Low', 'Medium Low', 'Medium', 'Medium High', 'High']  %>
                    <%= student_detail_field.label :expectation, 'What are your expectations for the program?:' %>
                    <%= student_detail_field.text_area :expectation %>
                    <%= student_detail_field.label :length_of_stay, 'About how long will you be in town?:' %>
                    <%= student_detail_field.select :length_of_stay, ['Less than 1 Year', '1 Year', '1-2 Years', '2-3 Years', '3+ Years'] %>
                    <%= student_detail_field.label :exact_length, 'Please tell us exactly how long you plan to be in town:' %>
                    <%= student_detail_field.text_area :exact_length %>
        <% end %>



Models:

    class Participant < ApplicationRecord
    validates :last_name, presence: true
    # validates :gender, inclusion: { in: %w(male female) }
    validates :phone, presence: true
    has_one :volunteer_detail, :dependent => :destroy
      accepts_nested_attributes_for :volunteer_detail,   :allow_destroy => :true

    has_one :student_detail, :dependent => :destroy
      accepts_nested_attributes_for :student_detail,   :allow_destroy => :true

     end

-

     class StudentDetail < ApplicationRecord
belongs_to :participant
  end

Controller:

                    class ParticipantsController < ApplicationController
            def new
            @participant= Participant.new
            @studentdetail= @participant.build_student_detail(participant: @participant)
            end



            def create
            @participant = Participant.create(participant_params)
            @participant.save
            if @participant.save
            flash[:success] = "Successfully Registered!"        

            #email notifes admin of new registration
            NotifyMailer.notify_email(@participant).deliver_later

            redirect_to '/signup'
            end
            end

            def edit
            end

            def update
            end

            def show
            end

            def index
            end

            private
            def participant_params
            params.require(:participant).permit(:first_name, :last_name, :gender, :email, :birthdate, :phone, 
              :street_name, :city, :state, :zip, student_detail_attributes: [:nationality, :religion, :need_ride, 
            :has_spouse, :spouse_name, :english_level, :expectation, :length_of_stay, :exact_length, :volunteer_id, 
            :matched, :returned_home, :participant_id])

            end


            end

Any suggestions or advice is appreciated, I'm trying to get both models to populate with data when the form is submitted, and currently the primary model is the only one working.

回答1:

I believe the problem here is with the syntax of your fields_for line in your view.

Change f.fields_for @participant.student_detail do |student_detail_field|

To f.fields_for :student_detail, @participant.student_detail do |student_detail_field|

I would bet if you put a binging.pry or a puts statement in your controller to see your params the student_detail_attributes aren't even getting to your params. You can just insert puts params.inspect in your controller to check if the params are coming through as you expect them. Your strong params syntax looks correct as do the models so I think this is an issue with your views.

EDIT

Here's a couple other things to try. As I mentioned in my comment, I normally would not do

@participant = Participant.create(participant_params)

I would just do:

@participant = Participant.new(participant_params)
if @participant.save
#etc
end

The above will also clean up your code a little. (Also I noticed you don't have a case in this action for what to do when the participant doesn't save - as a side note you should write some code to handle that)

Also if neither of these above work, sometimes I find with accept_nested_attributes I have to set the models as "inverse" of one another. See this article for more information: https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through -- its about a has_many but I think it should also relate to a has_one -- try in the Participant model:

has_one :student_detail, :dependent => :destroy, inverse_of: :participant

See if either of the above (or a combo of both) gets that nested model saving.