Take the 2-minute tour ×

I'm inserting =f.fields_for :customer in the second partial of a multi step form as described here. It works fine if it's on the first step of the form (_voucher_partial.html.haml), but won't display at all if I move it into the second. Can anyone tell me why, and how to fix? I don't understand why they'd be treated differently by Rails.



class Order < ActiveRecord::Base
  attr_accessible :customer_attributes, :customer_id, :format

  belongs_to :customer
  accepts_nested_attributes_for :customer
  attr_writer :current_step

  def steps
    %w[voucher recipient delivery confirmation]

  def current_step
    @current_step || steps.first

  def next_step
    self.current_step = steps[steps.index(current_step)+1]

  def previous_step
    self.current_step = steps[steps.index(current_step)-1]

  def first_step?
    current_step == steps.first

  def last_step?
    current_step == steps.last


  # GET /orders/new
  # GET /orders/new.json
  def new
    session[:order_params] ||= {}
    @order = Order.new(session[:order_params])
    @order.current_step = session[:order_step]

  # POST /orders
  # POST /orders.json
  def create
    session[:order_params].deep_merge!(params[:order]) if params[:order]
    @order = Order.new(session[:order_params])
    @order.current_step = session[:order_step]
    if params[:back_button]
    elsif @order.last_step?
    session[:order_step] = @order.current_step

    if @order.new_record?
      render 'new'
      session[:order_step] = session[:order_params] = nil
      flash[:notice] = "Order saved."
      redirect_to @order


%h1 New order

= form_for(@order) do |f|
  - if @order.errors.any?
        = pluralize(@order.errors.count, "error")
        prohibited this order from being saved:
        - @order.errors.full_messages.each do |msg|
          %li= msg
  = render "#{@order.current_step}_step", :f => f 
  = f.submit "Continue"
  = f.submit "Back", :name => "back_button" unless @order.first_step?

= link_to 'Back', orders_path


  Customer details

=f.fields_for :customer do |builder|
  =builder.label :name
  =builder.text_field :name

  =builder.label :email
  =builder.text_field :email

  Recipient details

  = f.label :recipient_name
  = f.text_field :recipient_name
share|improve this question
Can you post the view in which you add the partials? –  Lazarus Lazaridis Apr 30 '13 at 13:32
Added, hope that makes sense. –  Nick Apr 30 '13 at 13:35
add comment

1 Answer

Can you try rendering the partials this way:

= render partial: "#{@order.current_step}_step", object: @order, locals: { :f => f }

By the way, on your create action, you always create a new Order, but customer is not rebuilt!

share|improve this answer
I've edited the new.html.haml with that code but it's still not showing the fields for the customer... –  Nick Apr 30 '13 at 14:06
Does it render anything from the partial? The "Customer details" header for example? –  Lazarus Lazaridis Apr 30 '13 at 14:17
Yep, it renders the header, but no fields - the HTML source shows there's nothing on the page. –  Nick Apr 30 '13 at 14:36
Please view my updated post above. On each call of the "create" action you create a new order but its customer field is nil, I believe that this is the problem! You should rebuild the association! –  Lazarus Lazaridis Apr 30 '13 at 14:38
Hmmm. I tried to add @order.build_customer(session[:order_params]) into the create action - it's started throwing a new error "Can't mass-assign protected attributes". I've already set these up in the Order model though? –  Nick Apr 30 '13 at 15:34
show 1 more comment

Your Answer


