在Rails中允许嵌套属性的强参数的正确方法

时间:2017-10-15 09:34:19

标签: ruby-on-rails ruby nested-attributes strong-parameters

我的模型名为note.rb,如下所示:

class Note < ApplicationRecord
    belongs_to :user
    has_many :tags
    accepts_nested_attributes_for :tags
end

还有一个名为tag.rb的模型:

class Tag < ApplicationRecord
    belongs_to :note
end

新笔记创建的表单如下:

<%= form_with scope: :note, url: notes_path, local: true do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :description %><br>
    <%= f.text_area :description %>
  </p>
    <%= f.fields_for :tags_attributes do |t| %>
    <p>
      <%= label_tag(:name, "Add a tag") %><br>
      <%= t.text_field :name %>

    </p>    

    <% end %>

  <p>
    <%= f.submit %>
  </p>
<% end %>
<div id= "tag-displayer">
   <span id= "tags"></span>
</div>

我正在尝试使用记录笔记创建标记记录。

在我的notes_controller.rb中我有

def create
    @note = Note.new(note_params) 
    @note.user = current_user
    if @note.save 
      redirect_to '/notes'
    else 
      render 'new' 
    end         
end

和:

private
  def note_params
    params.require(:note).permit(:title, :description, tags_attributes: [:id, :name])
  end

现在,在表单提交中,我得到以下内容:

TypeError (no implicit conversion of Symbol into Integer):

如果我使用,我会收到同样的错误:

params.require(:note).permit(:title, :description, :tags_attributes => [:id, :name])

我收到错误:

Unpermitted parameter: :tags_attributes

如果我使用:

params.require(:note).permit(:title, :description, :tags_attributes => [])

表单提交的参数:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"iSsLyOb0ZxZP0rfB4I5yfyrw965zJSLrtkroTUzseY2k4o5DwKpKXlyxN6p99pt4Fwju1RhMZPkbNdv+YVSESQ==", "note"=>{"title"=>"test note with Tag", "description"=>"Test note with tag", "tags_attributes"=>{"name"=>"Rails"}}, "commit"=>"Save Note"}

我不确定我做错了什么,我已经尝试了所有可能的解决方案。

将Rails 5与ruby 2.4.1一起使用。

4 个答案:

答案 0 :(得分:0)

好吧,如果我看看你的params,你确实有字符串。有几种方法可以解决这个问题,但在我看来,最简单的方法就是允许字符串而不是符号。对于tags_attributes,应为'tags_attributes'=&gt; ...,其余的我不确定我是否记得正确:它可能是'标题'或''标题',可能是后者。我认为“注意”或“注意”也是如此。我希望你能玩一下,看看它是哪一个。之前我有错误,所以我很确定应该修复它。我希望我能帮忙!请让我知道哪一个修好了,我很想知道:)

答案 1 :(得分:0)

我认为你不需要在强参数中添加id

试试这个: -

params.require(:note).permit(:title, :description, tags_attributes: [:name])

答案 2 :(得分:0)

当前的问题是您的表单正在传递:

{..., "tags_attributes"=>{"name"=>"Rails"}}, ...}

需要通过时:

{..., "tags_attributes"=>[{"name"=>"Rails"}], ...}  # The hash is inside an array.

或者可能:

{..., "tags_attributes"=>{"any_key_except_id" => {"name"=>"Rails"}}, ...} 

我非常确定TypeError来自该问题,可能在某些时候它试图将字符串"Rails"视为哈希并尝试调用{ {1}}就可以了。

我的预感(没有复制整个设置)是可以通过改变你的行来解决这个问题:

"Rails"[:id]

    <%= f.fields_for :tags_attributes do |t| %>

如果您查看documentation for fields_for,它会使用关联的名称,而最后没有 <%= f.fields_for :tags do |t| %> 。对于_attributes,我认为表单不知道如何处理它,假设它是单个项目而不是集合,因此不会将属性嵌套在数组中。

请注意,如果您想让它显示新标记的字段(而不仅仅是现有标记),我相信您必须在:tags_attributes调用之前的某个地方调用@note.tags.build以便fields_for集合中有未保存的Tag实体。

答案 3 :(得分:0)

我认为这与宣布has_many :tags的模型和作为对象:tags_attributes => {id: "", name: ""}的表单数据有关。

当您尝试保存注释TypeError (no implicit conversion of Symbol into Integer):或使用@note.save初始化注释时,@note = Note.new(note_params)错误可能会冒泡,但不是因为强参数。强参数应允许这些参数,因为定义与您发送的表单数据匹配。

尝试修改前端以像:tags_attributes => [{id: "", name: ""}, {id: "", name: ""}]

这样的数组格式发送标记

博客几乎与您面临的问题不太相似,请查看http://billpatrianakos.me/blog/2013/09/29/rails-tricky-error-no-implicit-conversion-from-symbol-to-integer/