ruby-on-railsrubyformshas-many-throughaccepts-nested-attributes

Rails 5 - Strong Parameters for Nested Attributes


I am having trouble structuring my nested attributes for my model Request.

The data is being passed in the correct way from my POST action.

What am I missing to whitelist these parameters?

Appreciate any help.

Console Output

Started POST "/requests" for 127.0.0.1 at 2017-06-08 10:57:15 -0400
Processing by RequestsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"fmvhoPxVpcHoqOd32mO/HJMrfaPUd+KbNqDJiSRs78U44Y0uL3prpTfU6wmw7PAwv0b+mRHXOGMLvD9bsZpxnw==", "request"=>{"concierge_name"=>"Alex", "concierge_number"=>"954-123-4567", "concierge_email"=>"alex@email.com", "client_name"=>"Adam", "client_number"=>"954-765-4321", "client_email"=>"adam@email.com", "hotel_employee"=>"0", "concierge_service"=>"0", "vip_promoter"=>"0", "arriving_with_client"=>"1", "client_alone"=>"0", "males"=>"", "females"=>"1", "table_minimum"=>"1000", "arrival_time(1i)"=>"2017", "arrival_time(2i)"=>"6", "arrival_time(3i)"=>"8", "arrival_time(4i)"=>"14", "arrival_time(5i)"=>"56", "table_location_ids"=>["1"], "drink_attributes"=>[{"id"=>"1", "quantity"=>"1"}, {"id"=>"2", "quantity"=>""}, {"id"=>"3", "quantity"=>""}, {"id"=>"4", "quantity"=>""}], "chaser_ids"=>["1"], "comments"=>""}, "commit"=>"Submit"}
Completed 500 Internal Server Error in 8ms (ActiveRecord: 0.0ms)



ActiveModel::UnknownAttributeError (unknown attribute 'drink_attributes' for Request.):

app/models/request.rb

class Request < ApplicationRecord
    has_many :request_drinks
    has_many :drinks, through: :request_drinks

    accepts_nested_attributes_for :drinks
end

app/model/drink.rb

class Drink < ApplicationRecord
    has_many :request_drinks
    has_many :requests, through: :request_drinks
end

app/model/request_drink.rb

class RequestDrink < ApplicationRecord
    belongs_to :request
    belongs_to :drink
end

app/controllers/request_controller.rb

class RequestsController < ApplicationController
  before_action :set_request, only: [:show,
                                     :edit,
                                     :update,
                                     :destroy]

  def index
    @requests = Request.search(params[:term], params[:filter], params[:page])
  end

  def show
  end

  def new
    @request = Request.new
    @drinks = Drink.active
  end

  def edit
  end

  def create
    @request = Request.new(request_params)

    respond_to do |format|
      if @request.save
        format.html { redirect_to thanks_path, notice: 'Request was successfully created.' }
        format.json { render :show, status: :created, location: @request }
      else
        format.html { render :new }
        format.json { render json: @request.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @request.update(request_params)
        format.html { redirect_to @request, notice: 'Request was successfully updated.' }
        format.json { render :show, status: :ok, location: @request }
      else
        format.html { render :edit }
        format.json { render json: @request.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @request.destroy
    respond_to do |format|
      format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    def set_request
      @request = Request.find(params[:id])
    end

    def request_params
      params.require(:request).permit(:concierge_name,
                                      :concierge_number,
                                      :concierge_email,
                                      :client_name,
                                      :client_number,
                                      :client_email,
                                      :hotel_employee,
                                      :concierge_service,
                                      :vip_promoter,
                                      :arriving_with_client,
                                      :client_alone,
                                      :people,
                                      :males,
                                      :females,
                                      :table_minimum,
                                      :arrival_time,
                                      :comments,
                                      :drink_attributes => [:id, :quantity]
      )
    end
end

app/views/requests/_form.html.erb

...
    <div class="field-3">
      <h4>Drinks</h4>
      <% @drinks.all.each do |d| %>
        <%= hidden_field_tag "request[drink_attributes][][id]", d.id %>
        <%= number_field_tag "request[drink_attributes][][quantity]" %>
        <%= d.name %>
        <br />
      <% end %>
    </div>
...

Solution

  • You need to use the plural form of the object (i.e. drinks) when using nested attributes.

    So, in your request_params change:

    :drink_attributes => [:id, :quantity]
    

    to:

    :drinks_attributes => [:id, :quantity]
    

    An you need to update your form too:

    ...
      <%= hidden_field_tag "request[drinks_attributes][][id]", d.id %>
      <%= number_field_tag "request[drinks_attributes][][quantity]" %>
    ...