AnthonyGalli.com
AnthonyGalli.com

Reputation: 2866

How to submit nested attributes via parent _form submit?

Upon clicking submit only the Duel attributes are passing - not Dueler.

duels_controller.rb

  def new
    @duel = Duel.new
    @user = User.find(params[:challenge_daddy]) # This pulls in the ID for Challenged User

    # Current User
    @duel.duelers << Dueler.new(user_id: current_user.id, user_name: current_user.name, user_last_name: current_user.last_name)
    @current_user_challenges = current_user.challenges.order(:created_at)

    # Challenged User
    @duel.duelers << Dueler.new(user_id: @user.id, user_name: @user.name, user_last_name: @user.last_name)
    @challenged_user_challenges = @user.challenges.order(:created_at)

    respond_with(@duel)
  end

I think I have to submerge the dueler info (i.e. full_name and collection_select) within something like <%= simple_form_for(@dueler) do |f| %>, but then I don't want two separate submit buttons. When the user clicks submit the dueler and duel information should both submit since they go hand-in-hand. Right now only the duel information submits and the duelers are never created.

duels/_form.html.erb

<%= simple_form_for(@duel) do |f| %>
  <%= current_user.full_name %> WILL <%= collection_select(:dueler, :challenge_id, @current_user_challenges, :id, :full_challenge, include_blank: true) %>
  <%= @user.full_name %> WILL <%= collection_select(:dueler, :challenge_id, @challenged_user_challenges, :id, :full_challenge, include_blank: true) %>

  THE LOSER WILL <%= f.text_field :consequence %>.
  <%= f.submit %>
<% end %>

UPDATE

Originally I had this in the _form:

<%= f.fields_for :duelers do |dueler| %>
  <%= render 'dueler_fields', :f => dueler %>
<% end %>

But I took it out because the duels_controller new logic wasn't passing into it so I moved the code directly into the _form, but now I'm not sure what should take the place of <%= f.fields_for :duelers do |dueler| %>

class Dueler < ActiveRecord::Base
  belongs_to :user
  belongs_to :challenge
  belongs_to :duel
end

class Duel < ActiveRecord::Base
  belongs_to :user
  belongs_to :challenge
  has_many :duelers
  accepts_nested_attributes_for :duelers, :reject_if => :all_blank, :allow_destroy => true #correct
end

class DuelsController < ApplicationController
  before_action :set_duel, only: [:show, :edit, :update, :destroy, :duel_request]
  respond_to :html

  def index
    @duels = Duel.joins(:duelers).all
    redirect_to duel(@duel)
  end

  def duel_request
    @dueler = @duel.duelers.where(user_id: current_user)
  end   

  def show
    @dueler = Dueler.find_by(user_id: current_user.id)
    respond_with(@duel)
  end

  def user_challenges
    @user = User.find_by_name(params[:name])
    @challenges = @user.challenges.order(:created_at)
  end

  def new
    @duel = Duel.new
    @user = User.find(params[:challenge_daddy])
    @duel.duelers << Dueler.new(user_id: current_user.id, user_name: current_user.name, user_last_name: current_user.last_name)
    @current_user_challenges = current_user.challenges.order(:created_at)
    @duel.duelers << Dueler.new(user_id: @user.id, user_name: @user.name, user_last_name: @user.last_name)
    @challenged_user_challenges = @user.challenges.order(:created_at)
    respond_with(@duel)
  end

  def edit
  end

  def create
    @duel = Duel.new(duel_params)
    @duel.save
    #redirect_to duel_request_url(@duel)
    respond_with(@duel)
  end

  def update
    @duel.update(duel_params[:duelers_attributes])
    respond_with(@duel)
  end

  def destroy
    @duel.destroy
    respond_with(@duel)
  end

  private
    def set_duel
      @duel = Duel.find(params[:id])
    end

    def duel_params
      params.require(:duel).permit(:consequence, :reward, duelers_attributes: [:id, :user_id, :challenge_id, :accept])
    end
end

Upvotes: 0

Views: 50

Answers (1)

David
David

Reputation: 3610

If you are using has_many and belongs_to with accepts_nested_attributes you will need to use inverse_of to prevent Rails from attempting to lookup records (which of course don't exist because you haven't yet created them)

Change your Duel model has_many declaration to:

  has_many :duelers, inverse_of: :duel

For further details on this and an example of a nested form with has_many relationship using Simple Forms check out:

https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through

Upvotes: 1

Related Questions