1

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?

Amin Y
  • 701
  • 1
  • 9
  • 15

2 Answers2

2

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

Community
  • 1
  • 1
Naveed
  • 11,057
  • 2
  • 44
  • 63
2

Alternatively you could just not use accepts_nested_attributes (and still use fields_for). The user data will then be in params[:user] (or params[:order][:user], or params[:users], not sure, just look in server log, after you remove accepts_nested_attributes because that will change the field name). So you can just create the user manually first in the controller create action:

@user = current_user || User.create!(params[:user])
@order = @user.orders.build(params[:order])

The extra benefit is that you have a little more control this way and it's only 1 line more.

mrbrdo
  • 7,968
  • 4
  • 32
  • 36