Search code examples
ruby-on-rails-3activerecordnested-attributes

accepts_nested_attributes_for + belongs_to does not show fields


I have two models:

class User < ActiveRecord::Base
  acts_as_authentic
  has_many :orders
end

and

class Order < ActiveRecord::Base
  belongs_to :user
  accepts_nested_attributes_for :user
end

the idea is that if the user is already logged in, I just want to make a order for that user, but if he is not logged in, then I will ask him to register in the same time as making order. here is the form for orders

<%= form_for(@order) do |f| %>
  <div class="field">
    <%= f.label :quantity %><br />
    <%= f.number_field :quantity %>
  </div>

  <% if current_user %>
  <div class="field">
    <%= current_user.email%>
  </div>
  <%else%>
    <%= f.fields_for(:user) do |user_form| %>
        <%= render "newuser_fields", :f => user_form %>
    <% end %>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

and new users fields are:

<div class="field">
  <%= f.label :email %><br />
  <%= f.text_field :email %>
</div>
<div class="field">
  <%= f.label :password %><br />
  <%= f.password_field :password %>
</div>
<div class="field">
  <%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation %>
</div>

The problem is that it won't show fields for user!

Any suggestions?


Solution

  • User has many orders so accepts_nested_attributes_for will be used in User model.

    http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

    Nested resources can't be saved if the parent is not present, so you will create the user first and then create its orders.

    Usually, if user doesn't exist will be redirected to the signup page. If you don't want so you can do something like following on your in your OrderController#new action

    if current_user
      @order=current_user.orders.build
    else
      @user=User.new
    end
    

    And in your order form you can check if user is signin simply create order form if not create user form and then add nested filed for order

    # app/views/order/_form.html.erb
    <% if user_signed_in? %>
      //order form
    
    <% else %>
      // user form 
      <% form_for @user do |uf| %>
        <%= uf.text_filed :email %>
        <%= uf.password_filed :password %>
        //now order fileds
        <%= uf.fields_for :orders do |of| %>
          //porder fileds 
        <% end %>
      <% end %>
    <% end %>
    

    Then in create action for user and order you have to add appropriate check

    Here is a hack showing how you can use accepts_nested_attributes_for with belongs_to:

    accepts_nested_attributes_for with belongs_to polymorphic