【问题标题】:Ruby on rails Common error: Params missing?Ruby on rails 常见错误:缺少参数?
【发布时间】:2016-02-13 20:47:07
【问题描述】:

我正在构建一个订单管理系统。我最近发布了一个关于向客户添加订单的问题。看来我已经修复了 99%。如果我查看我的终端,它首先会找到当前的客户 ID,然后创建一个新订单。结果如下。

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

但问题是,它没有添加参数。我故意这样做只是为了检查我的语法是否会执行以下 sql 语句。但是,一旦我添加了参数,我就会收到一个常见错误“参数丢失或值为空:订单”

这是我的代码:

控制器

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

查看

<%= 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>

错误信息

OrderController#createorders 中的 ActionController::ParameterMissing 参数缺失或值为空:order

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


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

服务器端日志

于 2015 年 11 月 13 日开始为 ::1 获取“/order/createorders?id=111” 11:58:30 +0100 由 OrderController#createorders 处理为 HTML
参数:{"id"=>"111"} 客户负载 (0.2ms) SELECT "客户".* FROM "客户" WHERE "客户"."id" = ?限制 1 [["id", 111]] 5ms 完成 400 Bad Request (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) 渲染 /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 ) 渲染 /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) 渲染 /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 在救援/布局(68.2ms)内渲染 /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) 渲染 /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 在 layouts/inlined_string (0.4ms) 内渲染 /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 在 layouts/inlined_string (0.4ms) 内渲染 /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 在 layouts/inlined_string (0.4ms) 内渲染 /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 在 layouts/javascript (60.3ms) 内渲染 /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 在 layouts/javascript (0.3ms) 内渲染 /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 在 layouts/javascript ( 0.5ms) 渲染 /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.2 毫秒)

感谢 stackoverflow 对我的支持。我是红宝石的新手,我知道我犯了菜鸟错误。所以欢迎指出缺陷!

【问题讨论】:

  • 您的order_params 方法定义在哪里?
  • 是的,您正在显示customer_params,但您正在呼叫order_paramsorder_params 在哪里?
  • @sunnK,我粘贴了错误的参数。我现在粘贴了正确的
  • 您能否添加显示正在发送到createorders 操作的参数的日志?
  • @basia 是的!做到了。

标签: ruby-on-rails ruby-on-rails-3 activerecord associations


【解决方案1】:

我之前在专注于定位主要问题时忽略了您的次要、非致命问题,但现在主要问题已经明显,我将包括它们。

首先,我将稍微讨论一下 Rails 命名约定。您有两个模型,分别命名为 CustomerOrder。您已经为这些使用了名词的单数形式,这很好。模型的每个实例都是一回事,所以它应该是单数的。但是,Order 模型操作的控制器应使用复数形式命名,因此应将其命名为 OrdersController。这是因为它控制与您的所有订单相关的操作。这会将我们引向您的createorders 操作,如果将其命名为createorder 会更有意义,因为它只会创建一个Order。但实际上,惯例是将该操作命名为create。该操作在您的OrdersController 中,因此我们已经假设它处理Order 实例。 (当 Rails 使用 resources 函数为模型控制器自动生成 REST-ful 路由时,它假定您有一个名为 create 的操作。)最后,在您的 create 方法中,新的 Order 实例将在您的视图中引用的应称为@order 而不是@orders,因为它只包含一个Order

现在事情变得有点复杂了。你的param is missing 错误就是这个意思。缺少新的Order 实例的参数。对产生该错误的服务器的请求是一个 GET 请求,它只有一个参数,您在 URL 中提供了 ?id=111。您的表单数据没有通过 GET 请求提交到服务器。你应该做一个POST 请求来创建一个新的Order。我将避免进一步探索(以及在没有看到完整代码的情况下进行猜测)为什么现在不能正常工作,我只会建议一些关键的调整。在不查看所有部分的情况下弄清楚您的应用是如何工作的,这有点令人费解。

routes.rb 中,您应该有这一行:

resources :customers, :orders

我对您提供的视图做了最小的更改,我假设它称为 show.html.erb 并且位于您的 app/views/customers 文件夹中:

<%= 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>

这是来自 customers_controller.rb 的必要代码来支持它:

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

注意,在视图中,form_for 的参数是在控制器中创建的实例。另外,我添加了一个隐藏字段来提交 customer_id 和新的 Order 数据。

最后,您在 orders_controller.rb 中的 create 操作可能如下所示:

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

您的order_params 方法应更改为包含customer_id 参数:

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

请注意,在失败的save 上,操作会呈现customers/show,因为这是他们所在的页面,保存失败。这将允许 Rails 使用提交失败期间存在的数据重新填充表单(在相同的上下文中)。

【讨论】:

  • 谢谢,我注意到了你的建议。我已经编辑了代码。不幸的是同样的错误。而且我明白,如果你看过我的完整代码,你会更好地理解它。我有一个忏悔。我必须创建实例,第一个创建操作是针对客户的,第二个是针对订单的。第一个名为“create”,第二个名为“createorders”。这当然会造成混乱,但如果我把它们放在一起,我就无法创建客户。它甚至不允许我去表演场。然后我明白为什么参数是空的。但感谢您的建议和时间
  • 您在 customers_controller.rb 中的 'create` 操作应该创建一个 Customer,而您在 orders_controller.rb 中的 create 操作应该创建一个Order。当您开始像您一样即兴创作时,问题会迅速累积,最终您的表单中会出现GET 请求。这是我的建议:创建一个新应用程序,在窗口旁边打开一个文本编辑器,其中包含旧代码,然后按照 Rails 的预期使用方式编写应用程序。使用您现有的代码作为参考,但请确保您强制自己遵循 Rails 约定。你现在正在养成糟糕的习惯。
猜你喜欢
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多