与资源和未允许参数的accepts_nested_attributes_for的表单混淆



我的rails应用程序中有一个accepts_nested_attributes_for表单,我就是无法让它工作。当我试图编辑父对象时,我一直得到Unpermitted parameter,尽管我认为我已经允许了这个参数。

class Response < ApplicationRecord
has_many :response_threads, :dependent => :destroy
accepts_nested_attributes_for :response_threads
end
class ResponseThread < ApplicationRecord
belongs_to :response
has_many :response_thread_updates, :dependent => :destroy
accepts_nested_attributes_for :response_thread_updates
end
class ResponseThreadUpdate < ApplicationRecord
belongs_to :response_thread
end

responses_controller:中

def response_params
params.require(:response).permit(:name, :response_thread, response_thread_attributes: [:id, :name] )
end

/responses/1/edit:的表格

<%= form_with(model: response) do |f| %>
<%= f.fields_for :response_thread do |ff| %>

<%= ff.label :name %>
<%= ff.text_field :name %>

<% end %>

<div class="actions">
<%= f.submit %>
</div>
<% end %>

这是我的模式(更新和创建的日期时间删除(:

create_table "responses", force: :cascade do |t|
t.string "name"
end
create_table "response_threads", force: :cascade do |t|
t.integer "response_id"
t.string "name"
end
create_table "response_thread_updates", force: :cascade do |t|
t.integer "response_thread_id"
t.string "name"
end

错误:

Started PATCH "/responses/1" for ::1 at 2021-06-28 20:56:24 -0400
Processing by ResponsesController#update as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "response"=>{"response_thread"=>{"name"=>"asd"}}, "commit"=>"Update Response", "id"=>"1"}
Response Load (0.2ms)  SELECT "responses".* FROM "responses" WHERE "responses"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
↳ app/controllers/responses_controller.rb:63:in `set_response'
Unpermitted parameter: :response_thread

我的routes.rb:

Rails.application.routes.draw do
resources :responses do
resources :response_threads do
resources :response_thread_updates do
end
end
end

root to: "responses#new"
end

我正在编辑的response上有一个现有的response_thread。我甚至还没有尝试更新response_thread_update,因为我只赶上了第一级。应用程序没有其他更改,因为我创建了一个新的应用程序来解决这个问题。我只是在努力学习Rails,所以请告诉我我做错了什么!

首先,让我们检查StrongParameters如何允许属性:

  • StrongParameters包装您的输入参数(Hash(
  • 如果permit属性是标量(String或Symbol(,那么只有当您的输入params有任何等于该属性的键时,它才允许
  • 如果permit属性是Hash,那么它将遍历属性的键并检查每个标量(如上所述(,如果是空散列,它将允许任何内容

在您的情况下,您设置了一个permit属性response_thread作为标量,但您的输入参数包含一个Hashresponse_thread,因此StrongParameters找不到,它将返回Unpermitted parameter错误。

params = ActionController::Parameters.new({"response"=>{"response_thread"=>{"name"=>"asd"}}, "commit"=>"Update Response", "id"=>"1"}
# scalar
params.require(:response).permit(:response_thread) # Unpermitted parameter: :response_thread
# hash
params.require(:response).permit(response_thread: :name) # ok
params.require(:response).permit(response_thread: [:name]) # ok
# empty hash
params.require(:response).permit(response_thread: {}) # ok

其次,允许nested attributes的设置方式不正确,应该是params.require(:response).permit(:name, response_threads_attributes: [:id, :name])(注意response_threads不是response_thread(而且<%= f.fields_for :response_threads do |ff| %>

最新更新