Reputation: 310
Hello fellow programmers, I am building a application where i can add order to a existing customer. So far so good i can add a customer. But for a week now i am stuck adding a order to the customer. I am new with rails (a month now). I have associated the Customer and ID Model. This is my code.
Update: customer_id is a foreignkey in the order table
Customer Controller
class CustomerController < ApplicationController
def index
@customers = Customer.sorted
end
def new
@customers = Customer.new
#hij creert een nieuwe subject
end
def create
#Instantiate a new object using form paramters
@customer = Customer.new(customer_params)
#Save the object
if @customer.save
#If save succeeds, redirect to the inex acton
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
#If save fails, redisplay the form so user can fix problems
render('new') #het zit in de new.html template
end
end
def show
@customers = Customer.find(params[:id])
end
def edit
@customer = Customer.find(params[:id])
end
def delete
@customer = Customer.find(params[:id])
end
def destroy
customer = Customer.find(params[:id]).destroy #deze is zonder @ omdat het geen template rendert
flash[:notice] = "Subject '#{customer.first_name}' destroyed successfully"
redirect_to(:action => 'index')
end
private
def customer_params
params.require(:customer).permit(:first_name, :last_name)
end
end
Order Controller
class OrderController < ApplicationController
def index
@order = Order.find(params[:customer_id])
end
def new
@orders = Order.new
end
def create
@order = Order.new(order_params)
if @order.save
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
render 'customers/show'
end
end
end
def show
@order = Order.find(params[:customer_id])
end
def edit
end
def delete
end
private
def order_params
params.require(:order).permit(:customer_id, :pakket, :verstuurt)
end
Customer Show View
<% if !flash[:notice].blank? %>
<div class="notice">
<%= flash[:notice] %>
<% end %>
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subjects show">
<h2><%[email protected]_name %></h2>
<%= link_to("View Pages", {:controller => 'order', :customer_id => @customers.id}, :class => 'action show') %>
<%= link_to("Edit", {:action => 'edit', :id => @customers.id}, :class => 'action edit') %>
<%= link_to("Delete",{:action => 'delete', :id => @customers.id}, :class => 'action delete') %>
<%= link_to("Create",{:controller => 'order/create', :customer_id => @customers.id}, :class => 'action create') %>
</div>
Create a new Order to a existing customer page
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subject new">
<h2>Create Subject</h2>
<%= form_for @order do |f| %>
<table summary="subject form fields">
<tr>
<th>Package</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>Sent</th>
<td><%= f.text_field(:verstuurt) %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Create Subject") %>
</div>
<% end %>
</div>
Customer Model
class Customer < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders
scope :sorted, lambda { order("first_name ASC") }
scope :visible, lambda { where(:visible => true) }
scope :invisible, lambda { where(:visible => false) }
scope :newest_first, lambda { order("customers.created_at DESC")}
scope :search, lambda {|query|
}
end
Order Model
class Order < ActiveRecord::Base
belongs_to :customer
accepts_nested_attributes_for :customer
scope :visible, lambda { where(:visible => true) }
scope :invisible, lambda { where(:visible => false) }
scope :sorted, lambda { sorted("orders") }
scope :newest_first, lambda { order("orders.created_at DESC")}
scope :search, lambda {|query|
where(["name LIKE ?", "%#{query}%"])}
end
Error
ActionController::ParameterMissing in OrderController#create
param is missing or the value is empty: order
Extracted source (around line #34):
32
33
34
35
36
private
def order_params
params.require(:order).permit(:customer_id, :pakket, :verstuurt)
end
Server Log
Started GET "/order/create?customer_id=9" for ::1 at 2015-11-18 14:47:40 +0100
Processing by OrderController#create as HTML
Parameters: {"customer_id"=>"9"}
Customer Load (0.1ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1 [["id", 9]]
Completed 400 Bad Request in 2ms (ActiveRecord: 0.1ms)
ActionController::ParameterMissing (param is missing or the value is empty: order):
app/controllers/order_controller.rb:33:in `order_params'
app/controllers/order_controller.rb:14:in `create'
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_source.erb (4.1ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.0ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.0ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (56.6ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_markup.html.erb (0.4ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.4ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.4ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.4ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/console.js.erb within layouts/javascript (49.7ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/main.js.erb within layouts/javascript (0.4ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.5ms)
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/index.html.erb (111.1ms)
Upvotes: 1
Views: 840
Reputation: 2872
Change your /orders/new to this:
<%= form_for @order do |f| %>
<table summary="subject form fields">
<tr>
<th>Package</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>Sent</th>
<td><%= f.text_field(:verstuurt) %></td>
<%= f.hidden_field(:customer_id) %>
</tr>
</table>
<div class="form-buttons">
<%= f.submit %>
</div>
<% end %>
Upvotes: 0
Reputation: 76774
I am new with rails (a month now).
Keep at it - you need at least 3 apps before you start to "get it". You've done extremely well so far!!
Along with the other answers, there's a more immediate concern:
param is missing or the value is empty: order
This means that you're passing parameters to your controller which are not formatted as you need. This would either suggest your form or your controller code is incorrect.
--
The first port of call is here:
<div class="form-buttons">
<%= submit_tag("Create Subject") %>
</div>
It needs to be <%= f.submit %>
This should solve the immediate parameters error.
--
In regards to your broader question of how to associate an order
to a customer
, you need to look into nested resources:
#config/routes.rb
resources :customers do
resources :orders #-> url.com/customers/:customer_id/orders/:id
end
This will allow you to do the following:
#app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def new
@customer = Customer.find params[:customer_id]
@order = @customer.orders.new
end
def create
@customer = Customer.find params[:customer_id]
@order = @customer.orders.new order_params
@order.save
end
private
def order_params
params.require(:order).permit(:pakket, :verstuurt)
end
end
This will automatically set the foreign_key
for you; allowing you to call:
#app/views/orders/new.html.erb
<%= form_for @order do |f| %>
<%= f.text_field(:pakket) %>
<%= f.text_field(:verstuurt) %>
<%= f.submit %>
<% end %>
On the rare occasion that the Rails guides match the example, here's how your foreign key
should look:
Upvotes: 1
Reputation: 2872
You need to use nested routing if you wish to create a order that's already related to the customer:
#routes.rb
resources :customers do
resources :orders
end
This way you can make a new order for a specific customer using /customers/:customer_id/orders/new
Then in your OrderController use something like this:
def new
@customer = Customer.find(params[:customer_id])
@order = @customer.orders.build()
end
This way, the order is already related to the customer and the customer_id field in your form will be populated.
Edit: But this still allows creating orders for each customer without restriction. When I hear order & customer you will probably need authentication and authorization, so have a look at Devise so you can actually let a certain person order something. And when you are going to use that, you do not need the nested routes, because the customer_id will then be set just before saving.
Upvotes: 1
Reputation: 4164
Okay, I am not sure how you are trying to use your controller... but let us refactor your OrdersController as follow:
class OrdersController < ApplicationController
def index
@orders = <whatever you want it to be> # Note that I used the plural form of @orders, not @order
end
def new
customer = Customer.find(params[:customer_id])
@order = customer.order.new
end
def create
@order = Order.new(order_params)
if @order.save
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
render 'customers/show'
end
end
def show
@order = Order.find(params[:customer_id])
end
def edit
end
def delete
end
private
def order_params
params.require(:order).permit(:customer_id, :pakket, :verstuurt)
end
end
And then, in your form for order:
<%= form_for @order do |f| %>
<table summary="subject form fields">
<tr>
<th>Package</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>Sent</th>
<td><%= f.text_field(:verstuurt) %></td>
</tr>
</table>
<div class="form-buttons">
<%= f.submit %>
</div>
<% end %>
This should work fine for you.
Upvotes: 1