Reputation: 310
I am building a order management system that contains 2 tables. :customer
and :order
. I can destroy, show, and possibly edit. But I can only create for customer and not for order that comes with it. This is the code that I have so far:
class Order < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_many :orders
end
def new
@orders = Order.new
@customer = Customer.new ({:voornaam => "ABC"})
end
def create
@customer = Customer.new(customer_params)
if @customer.save
orders = Order.where(params(order_params))
@customer.orders << orders
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
render('new')
end
end
def customer_params
#same as using "params[:subject]", expect that it:
# - raises an error if :subject is not present
# - allows listed attributes to be mass-assigned
params.require(:customer).permit(:voornaam, :achternaam)
end
private
def order_params
#same as using "params[:subject]", expect that it:
# - raises an error if :subject is not present
# - allows listed attributes to be mass-assigned
params.require(:customer).permit(:pakket, :datum_bestelt, :verstuurt, :datum_verstuurt, :tweede_exemplaar, :packettracer_ID)
end
end
<%= form_for(:customer, :url=> {:action => 'create'}) do |f| %>
<table summary="subject form fields">
<tr>
<th>firstname</th>
<td><%= f.text_field(:voornaam) %></td>
</tr>
<tr>
<th>lastname</th>
<td><%= f.text_field(:achternaam) %></td>
</tr>
<%= f.fields_for :order do |s| %>
<tr>
<th>pakket</th>
<td><%= s.text_field(:pakket) %></td>
</tr>
<tr>
<th>datum_bestelt</th>
<td><%= s.text_field(:datum_bestelt) %></td>
</tr>
<tr>
<th>verstuurt</th>
<td><%= s.text_field(:verstuurt) %></td>
</tr>
<tr>
<th>datum_verstuurt</th>
<td><%= s.text_field(:datum_verstuurt) %></td>
</tr>
<tr>
<th>tweede_exemplaar</th>
<td><%= s.text_field(:tweede_exemplaar) %></td>
</tr>
<tr>
<th>packettracer_ID</th>
<td><%= s.text_field(:packettracer_ID) %></td>
</tr>
<% end %>
</table>
Upvotes: 1
Views: 91
Reputation: 101901
To create a customer and order in the same request you could use nested attributes:
class Order
belongs_to :customer
accepts_nested_attributes_for :customer
end
This would let you create a customer by:
Order.create(customer_attributes: { voornaam: 'Max' })
In a form you would add the inputs like so:
<%= form_for(:order) do |f| %>
<%= f.fields_for :customer do |cf| %>
<%= cf.text_field :voornaam %>
<% end %>
<% end %>
And this is how you would whitelist the parameters:
def order_params
params.require(:order)
.permit(
:foo, :bar,
customer_params: [
:voornaam,
# ...
]
)
end
However, from a UX perspective it might be better to split this into separate steps.
You may want to consider having a guest user record which you associate the order with until the user has created an account and signed in.
Upvotes: 2
Reputation: 1500
There might be a problem with this line in your controller :
orders = Order.where(params(order_params))
@customer.orders << orders
You're actually trying to fetch in the database an order corresponding to your params
, and to link it to @customer
. So if you want to create a new order with your params
, it won't find anything so orders
is always empty. Then you're appending an empty array to @customer.orders
.
What you can do instead is :
orders = @customer.orders.create(order_params)
Upvotes: 2