0

I've been struggling to get my nested form to save the users' inputs. The "outer" form saves the information perfectly. The "inner", or nested, one creates a new object, and passes hidden-field informations, but all other values are "nil".

Each order has one or more date_orders, and you should be able to create the first one through this form.

My code follows. Please help me spot anything that might be causing that. I've browsed StackOverflow extensively.

orders_controller.rb

class OrdersController < ApplicationController

def new
    @order = Order.new
    @order.date_orders.build
end

def create
    @order = Order.new(order_params)
    @order.date_orders.build
    if @order.save
        flash[:success] = "Success"
        redirect_to current_user
    else
        render 'new'
    end
end

def order_params
    params.require(:order).permit(
        :user_id, :description, date_order_attributes: 
            [:id, :order_date, :time_start, :time_end, :order_id])
end
end

order.rb

class Order < ActiveRecord::Base
    has_many :date_orders, :dependent => :destroy
    accepts_nested_attributes_for :date_orders
end

date_order.rb

class DateOrder < ActiveRecord::Base
    belongs_to :order
end

routes.rb --> date_orders is not mentioned in the routes. Is that a problem?

orders/new.html.erb

<%= form_for(@order, :html => {:multipart => true}) do |f| %>
<!-- form_for fields FIELDS -->
<%= fields_for :date_orders do |builder| %>

    <%= builder.hidden_field :order_id, :value => @order.id %> <- THIS WORKS

    <%= builder.label :date %>
    <%= builder.date_field :order_date %>

    <%= builder.label :starting_time %>
    <%= builder.time_field :time_start %>

    <%= builder.label :ending_time %>
    <%= builder.time_field :time_end %>


<% end %>
<%= f.submit "Request", class: "btn" %>
<% end %>

EDIT: example of a hash that is created:

<DateOrder id: 9, order_date: nil, time_start: nil, time_end: nil, order_id: 29, created_at: "2016-04-29 22:43:18", updated_at: "2016-04-29 22:43:18">enter code here`
8
  • 1
    @order.date_orders.build in the #create action is unnecessary. It builds a new object from scratch, which is not what you want - you only want to save the user input. Can you paste here an example for the params hash the #create action receives after submitting in the UI input that is not working properly for you? Commented Apr 29, 2016 at 23:14
  • Also, you don't need the hidden field. Commented Apr 29, 2016 at 23:17
  • 1
    Oh, you have a typo in the permit. It should be date_orders_attributes in plural. Please look at the server log rails s keeps spitting out - all non permitted attributes should get a warning. Make sure you don't have any. Commented Apr 29, 2016 at 23:19
  • Just added a hash that is created. Commented Apr 29, 2016 at 23:23
  • I meant the params hash the controller action #create receive, not a newly created date order object. Commented Apr 29, 2016 at 23:28

1 Answer 1

1

A few thoughts of how to debug these type of issues:

  1. Take a look at the server logs (the terminal window where you ran rails s). If strong parameters permit drops non-permitted attributes, you'll see a warning there. Make sure you don't have any typos, such as in your case (using date_order_attributes instead of date_orders_attributes).
  2. Submit form input in the UI that does not work, take a look at the server logs and find the params hash being sent. You can then debug your code by simply going to console and pasting the relevant keys from the params hash you send to Order.new. E.g.: Order.new(params['order'])

A few changes I would make in your code:

  1. Remove @order.date_orders.build from the #create action. This is something useful for #new to display an empty date order, but not in #create where you want to fully rely on the user input.
  2. Remove <%= builder.hidden_field :order_id, :value => @order.id %>. Rails does not need it. When you told rails accepts_nested_attributes_for :date_orders, it simply added a default date_orders_attributes= method to your model. When you send a hash that looks like hash = {order_title: 'my_title', date_orders_attributes: {order_date: '...'}}, to Order.new(hash), ActiveRecord sends the date_orders_attributes part of the hash to that method on that newly created order instance. I.e., this method already knows your child date orders belong to the order instance, so it is unnecessary.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.