【问题标题】:Required parameter missing - rails缺少必需的参数 - rails
【发布时间】:2013-10-24 00:27:07
【问题描述】:

我有这些相关的控制器型号:

class VendorsController < ApplicationController

  def vendor_params
      params.require(:vendor).permit(:id, :name, :address, :image, :latitude, :longitude)
  end

  def create
      vendor = Vendor.create(vendor_params)
      flash[:success] = "Vendor Created"
      redirect_to vendors_mgmt_path
  end

end

当我尝试创建新的供应商对象时,我收到以下错误:

Required parameter missing: vendor

这是我的表格:

<%= form_tag({controller: "vendors", action: "create"}, method: "post", multipart: true) do %>
<%= text_field_tag :name, "Store Name" %>
<%= text_field_tag :address, "Store Address" %>
<%= file_field_tag :image %>
<%= submit_tag "Save", class: "btn btn-success" %>
<% end %>

还有我对 Vendor 表的迁移:

class CreateVendors < ActiveRecord::Migration
  def change
    create_table :vendors do |t|

    t.string :name
    t.string :address
    t.float :latitude
    t.float :longitude
    t.string :image

    t.timestamps
    end
  end
end

有没有人知道我为什么会收到这个错误的线索?我不明白:vendor 本身如何是一个参数......非常感谢任何帮助。提前致谢!

这是我更新后的表格:

<%= form_for @vendor, multipart: true do |f| %>
<%= f.text_field :name, "Store Name" %>
<%= f.text_field :address, "Store Address" %>
<%= f.file_field :image %>
<%= f.submit "Save", class: "btn btn-success" %>
<% end %>

但我没有收到此错误:

undefined method `merge' for "Store Name":String

从我所做的搜索来看,这听起来像 rails 方法merge 只适用于哈希,而不是字符串。我不确定为什么它会尝试合并它,除非我的表单没有正确创建哈希?

我的新动作:

def new
    @vendors = Vendor.all
    @vendor = Vendor.new
end

服务器日志

Started GET "/vendors/new" for 127.0.0.1 at 2013-10-23 08:04:04 -0700
Processing by VendorsController#new as HTML
  Vendor Load (0.3ms)  SELECT "vendors".* FROM "vendors" 
Rendered vendors/new.html.erb within layouts/application (2.0ms)
Completed 500 Internal Server Error in 18ms

ActionView::Template::Error (undefined method `merge' for "Store Name":String):
    5: <h4>New Vendor Form</h4>
    6: 
    7: <%= form_for @vendor, multipart: true do |f| %>
    8: <%= f.text_field :name, "Store Name" %>
    9: <%= f.text_field :address, "Store Address" %>
    10: <%= f.file_field :image %>
    11: <%= f.submit "Save", class: "btn btn-success" %>
  app/views/vendors/new.html.erb:8:in `block in _app_views_vendors_new_html_erb__2593637676836103609_2161482240'
  app/views/vendors/new.html.erb:7:in `_app_views_vendors_new_html_erb__2593637676836103609_2161482240'


  Rendered /Users/******/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.8ms)
  Rendered /Users/******/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.4ms)
  Rendered /Users/******/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (11.9ms)

【问题讨论】:

    标签: ruby-on-rails devise strong-parameters


    【解决方案1】:

    问题是您没有正确使用form_for 发送参数。您直接使用form_tagtext_field_tag 等,只有在特定情况下才应该这样做,因为这会绕过 Rails 的大部分内置功能。您不需要指定值,因为它会自动由@vendor 中的内容填充。您可以制作标签来标记每个字段,如下例所示:

    <%= form_for @vendor, html: {multipart: true} do |f| %>
      <%= f.label :name, "Store Name" %>
      <%= f.text_field :name %>
      <%= f.label :address, "Store Address" %>
      <%= f.text_field :address %>
      <%= f.file_field :image %>
      <%= f.submit "Save", class: "btn btn-success" %>
    <% end %>
    

    在您的new 操作中,确保您实例化一个空的Vendor 对象,以便它知道在提交表单时将其发送到哪个控制器/操作。

    如果您不想使用标签来标记字段,您可以使用 html5 placeholder 属性来提供字段提示:

    <%= f.text_field :name, placeholder: "Store Name" %>
    

    【讨论】:

    • 我明白了,这是有道理的。我如上所述更新了我的表格。知道为什么我现在因为“Store Name”:String` 错误而被抛出 undefined method merge' 吗?
    • 哦,我真傻 ;) f.text_field 没有“值”参数,它从表单对象中获取值。我已经更新了我的答案。我认为您不需要为此提出新问题:p
    【解决方案2】:

    你的问题在这里:

    <%= form_tag({controller: "vendors", action: "create"}, method: "post", multipart: true) do %>
    

    具体来说,当您在 Rails 中“要求”使用 strong params 的参数时,它基本上期望 params hash 以这种方式构造:

    params{"vendor" => {"name":sdfadsf, "address": 23423}}
    

    只有在 new.html.erb 视图中使用form_for @vendor 才能实现这一点,因为这是 Rails 将初始值定义为 params 哈希的方式。您的应用正在做的是将参数哈希设置为:

    params{"name": 234234, "address: 234324}
    

    解决方案

    在您的 new.html.erb 表单中,只需使用以下代码:

    <%= form_for @vendor, method: "post", multipart: true) do %>
        <%= text_field_tag :name, "Store Name" %>
        <%= text_field_tag :address, "Store Address" %>
        <%= file_field_tag :image %>
        <%= submit_tag "Save", class: "btn btn-success" %>
    <% end %>
    

    【讨论】:

    • 这是一个很好的答案。很高兴知道有关强参数和形式的信息。你会检查我现在被抛出的错误吗?我已经用它更新了我的问题。
    • 没问题!有关于该错误的更多信息吗?我看不到你调用merge 命令的任何地方,如果你能提供任何其他信息会很好:)
    • 我以前从未见过这个错误,但从我所做的一些研究来看,这似乎与 Rails 呈现表单的方式有关(它本质上语法不好)。我实际上认为这是您的“多部分”定义,应该是这样的:&lt;%= form_for @vendor, :html =&gt; {:multipart =&gt; true} do |f|
    • 嗯...更新后的多部分定义出现同样的错误。我将为此提出一个新问题,所以我不会把这个问题偏离轨道,谢谢你的帮助!
    • 我认为第一个人(来自印度)为你找到了它 - 第二个参数应该是一个选项哈希,而不是一个值!
    【解决方案3】:

    除非我错过了一些不是很明显的东西--

    params.require(:vendor)
    

    您指定参数必须包含 :vendor。只需删除此子句,例如

    def vendor_params
      params.permit(:id, :name, :address, :image, :latitude, :longitude)
    end
    

    如果您的参数嵌套在:vendor 下,那么.require(:vendor) 将有意义。查看您的开发日志以查看传入的参数(如果您仍然遇到问题,请在此处分享)。

    【讨论】:

    • 我最初是这样设置我的vendor_params的,但是如果你不需要(:vendor)就会遇到问题。我的理解是:默认情况下,rails 表单中存在隐藏字段(例如authenticity_token),除非您需要(:vendor),否则不允许使用这些字段。从我本周提出的一个问题来看:link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 2018-10-28
    • 2018-12-01
    • 2016-06-29
    相关资源
    最近更新 更多