没有参数被发布到 Rails 控制器
No params being posted to Rails controller
我的应用程序中有一个表单,其中包含一些嵌套字段。
我正在使用 simple_form_for
、bootstrap、slim 和 Rails 4.2 以及 here
中描述的表单支持对象
这是服务器端缺少参数的证明(N.B。我检查了 authenticity_token
字段是否在标记中)
这是日志
Started POST "/example_sentences/9/breakdowns" for ::1 at 2015-08-31 12:37:57 +0900
ActiveRecord::SchemaMigration Load (18.8ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by BreakdownsController#create as HTML
Parameters: {"example_sentence_id"=>"9"}
Can't verify CSRF token authenticity
关闭 CSRF 保护以尝试调试会得到:
Started POST "/example_sentences/9/breakdowns" for ::1 at 2015-08-31 13:00:05 +0900
Processing by BreakdownsController#create as HTML
Parameters: {"example_sentence_id"=>"9"}
User Load (24.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Completed 400 Bad Request in 355ms (ActiveRecord: 156.3ms)
ActionController::ParameterMissing - param is missing or the value is empty: breakdown:
显然,有很多因素表明这偏离了 Rails 方式,所以很多事情都可能出错。显示视图代码会引入更多问题。
因此,我将展示生成的 HTML(减去样式信息)并询问是否有人能看出其中明显的错误。我有点希望这将是一个面面相觑的时刻,并且遗漏了一些明显的东西。
<form novalidate="novalidate" id="new_breakdown" action="/example_sentences/9/breakdowns" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="authenticity_token" value="cOU87EZXRkV1a0QA1ohwlqM5Ny43QvgcRaqKan9mdgs12jR8RnJfyVXp9VIJHkMRkBUvZ16Io7QaGcBazjVqGw==">
<input type="text" value="これ" name="breakdown[word_mapping][1][text]" id="breakdown_word_mapping_1_text" >
<input type="text" value="this" name="breakdown[word_mapping][1][translation]" id="breakdown_word_mapping_1_translation">
<input type="text" value="は" name="breakdown[word_mapping][2][text]" id="breakdown_word_mapping_2_text">
<input type="text" value="" name="breakdown[word_mapping][2][translation]" id="breakdown_word_mapping_2_translation">
<input type="submit" name="commit" value="Save translations">
</form>
附加信息
在~/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/request_forgery_protection.rb
在 :valid_authenticity_token?
检查第 277 行期间
对于 request.body.read 我可以看到真实性令牌
"utf8=%E2%9C%93&authenticity_token=RTFWCJZ3QnRgnNWFF66ej2aetx7H5n7BcbLKW4v145YADl6YllJb%2BEAeZNfIOK0IVbKvV64sJWkuAYBrOqb%2Fhg%3D%3D&breakdown%5Bword_mapping%5D%5B1%5D%5Btext%5D=%E3%81%93%E3%82%8C&breakdown%5Bword_mapping%5D%5B1%5D%5Btranslation%5D=this&breakdown%5Bword_mapping%5D%5B1%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B1%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B2%5D%5Btext%5D=%E3%81%AF&breakdown%5Bword_mapping%5D%5B2%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B2%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B2%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B3%5D%5Btext%5D=%E3%83%9A%E3%83%B3&breakdown%5Bword_mapping%5D%5B3%5D%5Btranslation%5D=pen&breakdown%5Bword_mapping%5D%5B3%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B3%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B4%5D%5Btext%5D=%E3%81%A7%E3%81%99&breakdown%5Bword_mapping%5D%5B4%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B4%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B4%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%81%93%E3%82%8C&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%81%AF&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%83%9A%E3%83%B3&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%81%A7%E3%81%99&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&commit=Save+translations"
但是encoded_masked_token
的值是nil
事实上,path_parameters
是我在请求中获得的参数的唯一部分。
in: "~/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_dispatch/http/request.rb"
(byebug) pp @env.keys.sort.grep(/action_dispatch/).grep(/param/).map{|k| [k, @env[k]]}
[["action_dispatch.parameter_filter", [:password]],
["action_dispatch.request.parameters",
{"controller"=>"breakdowns",
"action"=>"create",
"example_sentence_id"=>"9"}],
["action_dispatch.request.path_parameters",
{:controller=>"breakdowns", :action=>"create", :example_sentence_id=>"9"}],
["action_dispatch.request.query_parameters", {}],
["action_dispatch.request.request_parameters", {}]]
所以我已经以某种方式丢失了参数。
从错误消息来看,您要求参数的代码似乎不正确。
如果您遇到以下情况:
params.require(breakdown: [fields])
那么应该是
params.require(:breakdown).permit(fields)
试一试。
好的,问题出在名称参数的格式上。我没有弄清楚 Rails 堆栈中的确切位置,包括 authenticity_token/CSRF 令牌在内的所有参数都丢失了,但基本上:
而不是这个:
breakdown[word_mapping][0][translation]
这是正确的:
breakdown[word_mappings_attributes][0][translation]
可能值得添加额外的信息,以防其他人遇到类似问题。
我正在使用带有表单支持对象的嵌套表单,如 OP 中链接的关键博客 post 中所述。
我的 slim 代码看起来像这样,基于其他地方的过时推荐:
= f.simple_fields_for "word_mapping[]", @breakdown.word_mappings do |w|
= render "word_mapping_fields", f: w
这导致 post 中显示的输出 HTML。
正确的版本是:
= f.simple_fields_for "word_mappings", @breakdown.word_mappings do |w|
= render "word_mapping_fields", f: w
在我的表单支持对象上,我必须将 word_mappings_attributes=
委托给 AR
对象 ExampleSentence
在这种情况下。虽然使用 delegate
本身不起作用,所以我不得不手动编写代码。
def word_mappings_attributes=(attrs)
example_sentence.word_mappings_attributes=attrs
end
我还必须在表格中添加以下内容:
class << self
delegate :reflect_on_association, to: ExampleSentence
end
我的应用程序中有一个表单,其中包含一些嵌套字段。
我正在使用 simple_form_for
、bootstrap、slim 和 Rails 4.2 以及 here
这是服务器端缺少参数的证明(N.B。我检查了 authenticity_token
字段是否在标记中)
这是日志
Started POST "/example_sentences/9/breakdowns" for ::1 at 2015-08-31 12:37:57 +0900
ActiveRecord::SchemaMigration Load (18.8ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by BreakdownsController#create as HTML
Parameters: {"example_sentence_id"=>"9"}
Can't verify CSRF token authenticity
关闭 CSRF 保护以尝试调试会得到:
Started POST "/example_sentences/9/breakdowns" for ::1 at 2015-08-31 13:00:05 +0900
Processing by BreakdownsController#create as HTML
Parameters: {"example_sentence_id"=>"9"}
User Load (24.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Completed 400 Bad Request in 355ms (ActiveRecord: 156.3ms)
ActionController::ParameterMissing - param is missing or the value is empty: breakdown:
显然,有很多因素表明这偏离了 Rails 方式,所以很多事情都可能出错。显示视图代码会引入更多问题。
因此,我将展示生成的 HTML(减去样式信息)并询问是否有人能看出其中明显的错误。我有点希望这将是一个面面相觑的时刻,并且遗漏了一些明显的东西。
<form novalidate="novalidate" id="new_breakdown" action="/example_sentences/9/breakdowns" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="authenticity_token" value="cOU87EZXRkV1a0QA1ohwlqM5Ny43QvgcRaqKan9mdgs12jR8RnJfyVXp9VIJHkMRkBUvZ16Io7QaGcBazjVqGw==">
<input type="text" value="これ" name="breakdown[word_mapping][1][text]" id="breakdown_word_mapping_1_text" >
<input type="text" value="this" name="breakdown[word_mapping][1][translation]" id="breakdown_word_mapping_1_translation">
<input type="text" value="は" name="breakdown[word_mapping][2][text]" id="breakdown_word_mapping_2_text">
<input type="text" value="" name="breakdown[word_mapping][2][translation]" id="breakdown_word_mapping_2_translation">
<input type="submit" name="commit" value="Save translations">
</form>
附加信息
在~/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/request_forgery_protection.rb
在 :valid_authenticity_token?
检查第 277 行期间
对于 request.body.read 我可以看到真实性令牌 "utf8=%E2%9C%93&authenticity_token=RTFWCJZ3QnRgnNWFF66ej2aetx7H5n7BcbLKW4v145YADl6YllJb%2BEAeZNfIOK0IVbKvV64sJWkuAYBrOqb%2Fhg%3D%3D&breakdown%5Bword_mapping%5D%5B1%5D%5Btext%5D=%E3%81%93%E3%82%8C&breakdown%5Bword_mapping%5D%5B1%5D%5Btranslation%5D=this&breakdown%5Bword_mapping%5D%5B1%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B1%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B2%5D%5Btext%5D=%E3%81%AF&breakdown%5Bword_mapping%5D%5B2%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B2%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B2%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B3%5D%5Btext%5D=%E3%83%9A%E3%83%B3&breakdown%5Bword_mapping%5D%5B3%5D%5Btranslation%5D=pen&breakdown%5Bword_mapping%5D%5B3%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B3%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B4%5D%5Btext%5D=%E3%81%A7%E3%81%99&breakdown%5Bword_mapping%5D%5B4%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B4%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B4%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%81%93%E3%82%8C&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%81%AF&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%83%9A%E3%83%B3&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&breakdown%5Bword_mapping%5D%5B%5D%5Btext%5D=%E3%81%A7%E3%81%99&breakdown%5Bword_mapping%5D%5B%5D%5Btranslation%5D=&breakdown%5Bword_mapping%5D%5B%5D%5Breading%5D=&breakdown%5Bword_mapping%5D%5B%5D%5B_destroy%5D=0&commit=Save+translations"
但是encoded_masked_token
的值是nil
事实上,path_parameters
是我在请求中获得的参数的唯一部分。
in: "~/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_dispatch/http/request.rb"
(byebug) pp @env.keys.sort.grep(/action_dispatch/).grep(/param/).map{|k| [k, @env[k]]}
[["action_dispatch.parameter_filter", [:password]],
["action_dispatch.request.parameters",
{"controller"=>"breakdowns",
"action"=>"create",
"example_sentence_id"=>"9"}],
["action_dispatch.request.path_parameters",
{:controller=>"breakdowns", :action=>"create", :example_sentence_id=>"9"}],
["action_dispatch.request.query_parameters", {}],
["action_dispatch.request.request_parameters", {}]]
所以我已经以某种方式丢失了参数。
从错误消息来看,您要求参数的代码似乎不正确。
如果您遇到以下情况:
params.require(breakdown: [fields])
那么应该是
params.require(:breakdown).permit(fields)
试一试。
好的,问题出在名称参数的格式上。我没有弄清楚 Rails 堆栈中的确切位置,包括 authenticity_token/CSRF 令牌在内的所有参数都丢失了,但基本上:
而不是这个:
breakdown[word_mapping][0][translation]
这是正确的:
breakdown[word_mappings_attributes][0][translation]
可能值得添加额外的信息,以防其他人遇到类似问题。
我正在使用带有表单支持对象的嵌套表单,如 OP 中链接的关键博客 post 中所述。
我的 slim 代码看起来像这样,基于其他地方的过时推荐:
= f.simple_fields_for "word_mapping[]", @breakdown.word_mappings do |w|
= render "word_mapping_fields", f: w
这导致 post 中显示的输出 HTML。
正确的版本是:
= f.simple_fields_for "word_mappings", @breakdown.word_mappings do |w|
= render "word_mapping_fields", f: w
在我的表单支持对象上,我必须将 word_mappings_attributes=
委托给 AR
对象 ExampleSentence
在这种情况下。虽然使用 delegate
本身不起作用,所以我不得不手动编写代码。
def word_mappings_attributes=(attrs)
example_sentence.word_mappings_attributes=attrs
end
我还必须在表格中添加以下内容:
class << self
delegate :reflect_on_association, to: ExampleSentence
end