C.B.
C.B.

Reputation: 310

Ruby on rails Common error: Params missing?

I am building a Order management system. I recently posted a problem about adding a order to a customer. It seems that i have fixed it for 99%. if i look in my terminal it first finds the current customer ID and then creates a new order. The following result is.

Customer Load (0.2ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1 [["id", 111]] (0.1ms) begin transaction SQL (0.4ms) INSERT INTO "orders" ("customer_id", "created_at", "updated_at") VALUES (?, ?, ?) [["customer_id", 111], ["created_at", "2015-11-12 13:28:21.185604"], ["updated_at", "2015-11-12 13:28:21.185604"]] (8.2ms) commit transaction

But the problem is, it doesn't add the params. I did this intentionally just to check if my syntax would execute the following sql statement. But once i add params i get a common error "param is missing or the value is empty: order"

Here is my code:

Controller

def createorders
  @customer = Customer.find(params[:id]) #find current id??
  #current_user = Order.find(params[:id])
  @orders = @customer.orders.new(order_params)

  if @orders.save
    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

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(:order).permit(:pakket, :verstuurt)
  end
end

View

<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>

<div class="subject new">
    <h2>Create Subject</h2>

    <%= form_for(:order, :url=> {:action => 'createorders'}) do |f| %>
    <table summary="subject form fields">
        <tr>
            <th>pakket</th>
            <td><%= f.text_field(:pakket) %></td>
        </tr>
        <tr>
            <th>verstuurt</th>
            <td><%= f.text_field(:verstuurt) %></td>
        </tr>

    </table>

    <div class="form-buttons">
        <%= submit_tag("Create Subject") %>
    </div>

    <% end %>
</div>

Error message

ActionController::ParameterMissing in OrderController#createorders param is missing or the value is empty: order

Extracted source (around line #107):
105
106
107
108
109
110


  def order_params
  params.require(:order).permit(:pakket, :verstuurt)
      end
end

Serverside Log

Started GET "/order/createorders?id=111" for ::1 at 2015-11-13 11:58:30 +0100 Processing by OrderController#createorders as HTML
Parameters: {"id"=>"111"} Customer Load (0.2ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1 [["id", 111]] Completed 400 Bad Request in 5ms (ActiveRecord: 0.2ms)

ActionController::ParameterMissing (param is missing or the value is empty: order):   app/controllers/order_controller.rb:107:in

order_params' app/controllers/order_controller.rb:44:in createorders'

  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

(8.3ms) 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.6ms) 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.3ms) 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 (68.2ms) 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 (60.3ms) 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.3ms) 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 (124.2ms)

Thank you stackoverflow for showing me support. I am new with ruby, and i understand i am making noob mistakes. So pointing out flaws are welcome!

Upvotes: 0

Views: 2573

Answers (1)

Jason
Jason

Reputation: 2743

I was ignoring your minor, non-fatal issues earlier while I was focused on locating the major issue, but I'll include them now that the major issue is apparent.

First, I'll discuss Rails naming conventions a little bit. You have two models, which are named Customer and Order. You've used the singular form of the noun for these, which is good. Each instance of a model is one thing, so it should be singular. Your controller for the Order model actions, however, should be named with the plural form, so it should be called OrdersController. This is because it controls the actions related to all of your orders. This leads us to your createorders action, which would make a little more sense if it were named createorder, since it only creates one Order. Actually, though, the convention is to name that action create. The action is in your OrdersController, so we already assume that it deals with an Order instance. (When you have Rails automatically generate REST-ful routes for a model's controller with the resources function, it assumes you have an action named create.) Lastly, in your create method, the new Order instance that will be referenced in your view should be called @order instead of @orders, since it contains only one Order.

Now things get a little more complicated. Your param is missing error means exactly that. The parameters for the new Order instance are missing. The request to the server that is producing that error is a GET request that has only one parameter, which you're providing in your URL with ?id=111. Your form's data is not being submitted to the server with that GET request. You should be doing a POST request to create a new Order. I'm going to avoid further exploration (and speculation without seeing your full code) regarding why things aren't working right now and I'll just suggest some key adjustments. It's turning in to a bit a puzzle to figure out how your app works without seeing all of the pieces.

In routes.rb, you should have this line:

resources :customers, :orders

I've made minimal changes to the view you provided, which I assume is called show.html.erb and is in your app/views/customers folder:

<%= 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>pakket</th>
            <td><%= f.text_field(:pakket) %></td>
        </tr>
        <tr>
            <th>verstuurt</th>
            <td><%= f.text_field(:verstuurt) %></td>
        </tr>
    </table>
    <%= f.hidden_field :customer_id %>
    <div class="form-buttons">
        <%= submit_tag("Create Subject") %>
    </div>
    <% end %>
</div>

Here is the necessary code from customers_controller.rb to support it:

def show
    customer = Customer.find params[:id]
    @order = customer.orders.new
end

Notice, in the view, the parameter for form_for is the instance that was created in the controller. Also, I've added a hidden field to submit the customer_id with the new Order data.

Finally, your create action in orders_controller.rb might look like this:

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

And your order_params method should be changed to include the customer_id parameter:

def order_params
  params.require(:order).permit(:pakket, :verstuurt, :customer_id)
end

Notice that on a failed save, the action renders customers/show, because this is the page that they were on where the save failed. This will allow Rails to re-populate the form (in the same context) with the data that was present during the failed submission.

Upvotes: 0

Related Questions