简体   繁体   English

Rails 5 HABTM 不允许的参数

[英]Rails 5 HABTM Unpermitted parameters

I'm throwing in the towel after a day of getting nowhere (and the answer will likely be annoyingly simple, but that's code).在一天无处可去之后,我认输了(答案可能非常简单,但这就是代码)。

Ok, I have 2 models, User (with Devise) and Chapter.好的,我有 2 个模型,用户(带有设计)和章节。

Models:楷模:

class User < ApplicationRecord
  has_many :projects
  has_and_belongs_to_many :chapters
end

class Chapter < ApplicationRecord
  belongs_to :country
  has_and_belongs_to_many :users
  accepts_nested_attributes_for :users
end

_form.html.erb _form.html.erb

[...]
<% @chapter.users.each_with_index do |chap_user, i| %>
  <div class="row">
    <div class="col-md-4 col-md-offset-4  col-xs-8 col-xs-offset-2">
      <small>User <%= i + 1 %></small>
    </div>
  </div>

  <div class="row">
    <div class="col-md-2 col-md-offset-4  col-xs-8 col-xs-offset-2">

      <div class="field form-group">
        <%= form.label 'First Name' %>
        <%= form.text_field :first_name, value: chap_user.first_name,class:"form-control"%>
      </div>
    </div>
    <div class="col-md-2 col-md-offset-0 col-xs-8 col-xs-offset-2">
      <div class="field form-group">
        <%= form.label 'Last Name' %>
        <%= form.text_field :last_name, value: chap_user.last_name, class:"form-control"%>
      </div>

    </div>
  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-4 col-xs-8 col-xs-offset-2">
      <div class="field form-group">
        <%= form.label :email %>
        <%= form.text_field :email, value: chap_user.email, class:"form-control"%>
      </div>

    </div>
  </div>
<% end %>
[...]

ChaptersController (params) ChaptersController(参数)

private # Use callbacks to share common setup or constraints between actions. private # 使用回调来共享操作之间的通用设置或约束。 def set_chapter @chapter = Chapter.find(params[:id]) end def set_chapter @chapter = Chapter.find(params[:id]) end

# Never trust parameters from the scary internet, only allow the white list through.
def chapter_params
  params.fetch(:chapter, {})
  params.require(:chapter).permit(:city, :country_id, user_attributes: [:first_name,:last_name,:email])
end
# or...
params.require(:chapter).permit(:city, :country_id, user_ids: [])
# or...
params.require(:chapter).permit(:city, :country_id, user_attributes: [:id, :first_name])
# or...
params.require(:chapter).permit(:city, :country_id, users_attributes: [:id, :first_name])

binding.pry in controller控制器中的 binding.pry

  # PATCH/PUT /chapters/1
  # PATCH/PUT /chapters/1.json
  def update
    binding.pry
    respond_to do |format|
      if @chapter.update(chapter_params)
        format.html { redirect_to @chapter, notice: 'Chapter was successfully updated.' }
        format.json { render :show, status: :ok, location: @chapter }
      else
        format.html { render :edit }
        format.json { render json: @chapter.errors, status: :unprocessable_entity }
      end
    end
  end

binding.pry response binding.pry 响应

I know this one is a bit ugly but basically the params are being submitted but users[:first_name,:last_name,:email] aren't being permitted我知道这个有点难看,但基本上是提交了参数,但不允许 users[:first_name,:last_name,:email]

[1] pry(#)> chapter_params Unpermitted parameters: :first_name, :last_name, :email => "London", "country_id"=>"1"} permitted: true> [2] pry(#)> params => "✓", "_method"=>"patch", "authenticity_token"=>"9IdAqcAsVG5vvakSf7jHRk+WplN/GyVZUxmAdefUbTX/uI6IajmZPr1YSol21Zhzdl7P/lrl+SVnWr5mBMiljw==", "chapter"=>"London", "country_id"=>"1", "first_name"=>"Tim2", "last_name"=>"Heard", "email"=>"jmcgregorx@spartaglobal.com"} permitted: false>, "commit"=>"Update", "controller"=>"chapters", "action"=>"update", "id"=>"1"} permitted: false> [1] pry(#)>chapter_params 不允许的参数: :first_name, :last_name, :email => "London", "country_id"=>"1"} 允许: true> [2] pry(#)> params => "✓", "_method"=>"patch", "authenticity_token"=>"9IdAqcAsVG5vvakSf7jHRk+WplN/GyVZUxmAdefUbTX/uI6IajmZPr1YSol21Zhzdl7P/lrl+SVnWr5m",="="="=", SVnWr5m","="="jhzdlwr5m","="jhpL" ", "first_name"=>"Tim2", "last_name"=>"Heard", "email"=>"jmcgregorx@spartaglobal.com"} 允许: false>, "commit"=>"Update", "controller" =>“章节”、“动作”=>“更新”、“id”=>“1”} 允许:false>

In a nutshell, I want to connect certain users to certain chapters through a form, but I can't figure out how to get the nested params through the chapter update/create methods.简而言之,我想通过表单将某些用户连接到某些章节,但我不知道如何通过章节更新/创建方法获取嵌套参数。 My head is a red, pulpy mess.我的头是一团红色,一团糟。 Please help.请帮忙。

Since the fields you are trying to modify are for a child model, you have to tell the form that because it assumes that you're editing fields on parent model by default.由于您尝试修改的字段用于子模型,因此您必须告诉表单,因为它假定您在默认情况下正在编辑父模型上的字段。 The way to to that is by using #fields_for (specifically the the "One-to-Many" section).方法是使用#fields_for (特别是“一对多”部分)。

So you'll do something along these lines (explanation below code):所以你会按照这些方式做一些事情(代码下面的解释):

<% @chapter.users.each_with_index do |chap_user, i| %>
  <%= form.fields_for :users, chap_user do |user_fields| %>
    <div class="row">
      <div class="col-md-4 col-md-offset-4  col-xs-8 col-xs-offset-2">
        <small>User <%= i+ 1 %></small>
      </div>
    </div>

    <div class="row">
      <div class="col-md-2 col-md-offset-4  col-xs-8 col-xs-offset-2">
        <div class="field form-group">
          <%= user_fields.label 'First Name' %>
          <%= user_fields.text_field :first_name, value: chap_user.first_name,class:"form-control"%>
        </div>
      </div>
      <div class="col-md-2 col-md-offset-0 col-xs-8 col-xs-offset-2">
        <div class="field form-group">
          <%= user_fields.label 'Last Name' %>
          <%= user_fields.text_field :last_name, value: chap_user.last_name, class:"form-control"%>
        </div>
      </div>
    </div>

    <div class="row">
      <div class="col-md-4 col-md-offset-4 col-xs-8 col-xs-offset-2">
        <div class="field form-group">
          <%= user_fields.label :email %>
          <%= user_fields.text_field :email, value: chap_user.email, class:"form-control"%>
        </div>
      </div>
    </div>
  <% end %>
<% end %>

What changed is I wrapped all the form inputs in a block using the #fields_for method to specify that now we're modifying child attributes.改变的是我使用#fields_for方法将所有表单输入包装在一个块中,以指定现在我们正在修改子属性。 When we do so, we also specify a variable name that will be used to generate fields for the child model's attributes.当我们这样做时,我们还指定了一个变量名称,该名称将用于为子模型的属性生成字段。 I named it user_fields and then inside that block replaced all references of form with user_fields .我将它命名为user_fields ,然后在该块中用user_fields替换了所有form user_fields

In your ChaptersController, you want the line that accepts the params to be:在您的 ChaptersController 中,您希望接受参数的行是:

params.require(:chapter).permit(:city, :country_id, users_attributes: [:id, :first_name, :last_name, :email])

You'd want users_attributes and not user_attribute because the plural "users" tells rails to expect attributes for more than one child (more than one user).您需要users_attributes而不是user_attribute因为复数“users”告诉 rails 期望多个孩子(多个用户)的属性。 Then inside that array you want to tell it all the fields to expect, including id .然后在该数组中,您想告诉它所有期望的字段,包括id Even though you're not explicitly defining a field for the ID, Rails puts one to allow you to edit attributes for children that already exist (and not only be able to create new ones).即使您没有为 ID 显式定义一个字段,Rails 也会放置一个字段来允许您编辑已经存在的子项的属性(并且不仅能够创建新的子项)。 Snippet from the documentation:来自文档的片段:

Note that #fields_for will automatically generate a hidden field to store the ID of the record.请注意,#fields_for 会自动生成一个隐藏字段来存储记录的 ID。 There are circumstances where this hidden field is not needed and you can pass include_id: false to prevent #fields_for from rendering it automatically.在某些情况下不需要此隐藏字段,您可以传递 include_id: false 以防止 #fields_for 自动呈现它。

If something about this doesn't work, or if you have more questions, feel free to let me know!如果关于此的某些内容不起作用,或者您有更多问题,请随时告诉我!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM