【问题标题】:Unpermitted parameter for join table via multiple select in Rails在 Rails 中通过多选连接表的未经允许的参数
【发布时间】:2017-06-19 23:57:54
【问题描述】:

在 Rails 5 中嵌套参数时遇到错误:Unpermitted parameter: specialties

我有一个专家模型:

class Expertise < ApplicationRecord
    has_many :buckets, through: :specialties
    has_many :specialties   
end

桶模型:

class Bucket < ApplicationRecord
    has_many :expertises, through: :specialties
    has_many :specialties
end

还有一个专业模型:

class Specialty < ApplicationRecord
    belongs_to :expertise
    belongs_to :bucket
end

我正在尝试允许用户编辑他或她的专长并调整与其关联的专长。 @buckets 是从控制器传入的,当前表单如下所示:

<%= form_for(expertise) do |f| %>
    <%= f.fields_for :specialties do |s| %>
        <%= s.collection_select :bucket_ids, @buckets, :id, :name, {}, { multiple: true, class: "input" } %>
    <% end %>
<% end %>

我的表单基于this answer

这是来自 ExpertisesController 的相关 sn-p:

def expertise_params
    params.require(:expertise).permit(:user_id, :name, :rating, :description, specialties_attributes: [:id, :expertise_id, :bucket_id, :_destroy, bucket_ids: []])
end

下面是传入的参数:

Parameters: {"expertise"=>{"specialties"=>{"bucket_ids"=>["", "1"]}, "description"=>""}, "id"=>"97"}

Specialties 应该是一个数组,对吧?我不知道该怎么做。

目的是让用户轻松地从可用的存储桶 (@buckets) 中进行选择,以打开或关闭他或她的专长专长。因此,假设有 5 个可用存储桶,用户只能为该专长打开/关闭 5 个可能的专长。

【问题讨论】:

  • 您是否已经尝试将specialties_attributes 切换为specialties
  • 可以粘贴日志输出吗?
  • @ThiagoUruray,我试过了,但它抛出了一个错误:“Specialty expected, got Array”
  • @JCorcuera,从日志中添加了参数,你指的是这个吗?

标签: ruby-on-rails ruby forms nested-forms multiple-select


【解决方案1】:

不允许的参数:专业

你没有设置accept_nested_attributes_for,它会报错

class Expertise < ApplicationRecord
  has_many :specialties
  has_many :buckets, through: :specialties
  accepts_nested_attributes_for :specialties
end

当我尝试这样做时,嵌套的 fields_for 表单不返回任何 特产,因此 HTML 元素为空。然后,当我尝试使用 @expertise.specialties.build,我得到未定义的方法 bucket_ids 专业,因为 bucket_ids 实际上不是一个属性,而是 bucket_id 是。值得记住的是,用户需要能够 切换多个专业,每个专业都绑定到一个桶(通过 bucket_id),从我准备好的内容来看,我应该使用 bucket_ids (复数)那里

你不需要有复数形式(_ids),只是因为接受多个值。只需保留bucket_id 即可接受多个值。并且不要忘记在控制器中构建关联模型

定义新 @expertise = Expertise.new @expertise.specialties.build 结尾 将表单中的bucket_ids改为bucket_id

最后,expertise_params 应该是

def expertise_params
  params.require(:expertise).permit(:user_id, :name, :rating, :description, specialties_attributes: [:id, :expertise_id, :_destroy, bucket_id: []])
end

更新:

好吧,经过一番研究,它看起来应该是bucket_ids,但bucket_ids 应该允许作为expertise 的属性。检查此post 并相应地调整您的formexpertise_params。你也不需要accept_nested_attributes_for

【讨论】:

  • 感谢您的帮助。这让我更接近,但仍然不完全在那里。我现在可以保存专长,但它没有与之关联的存储桶。以下是参数,如果它们有帮助的话:"expertise"=&gt;{"specialties_attributes"=&gt;{"0"=&gt;{"bucket_id"=&gt;["", "1"]}}}
  • @Andrew 你能把你在服务器日志中收到的INSERT 调用贴出来吗?
  • 给你:INSERT INTO "specialties" ("expertise_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["expertise_id", 97], ["created_at", 2017-06-20 16:04:12 UTC], ["updated_at", 2017-06-20 16:04:12 UTC]]
  • @Andrew 好的,经过一番研究,它看起来应该是bucket_ids,但bucket_ids 应该被允许作为expertise 的属性。检查此帖子stackoverflow.com/questions/8826407/… 并调整您的formexpertise_params。你也不需要accept_nested_attributes_for
  • @Andrew 很高兴它起作用了 :) 我在回答中包含了一个更新,说明相同,因此您可以将其标记为已接受 :)
【解决方案2】:

情况:Expertise has_many Buckets 通过 Specialties 并且您想更新特定专业知识的某些桶状态。所以你可以这样做:

class ExpertisesController < ApplicationController
  def your_action
    @expertise = Expertise.find params[:id]
    bucket_ids = params[:expertise][:specialties][:bucket_ids]
    @expertise.specialties.where(id: bucket_ids).update(status: :on)
  end
end

【讨论】:

  • 我想根据选择的相应存储桶创建和删除专业对象,而不是更新专业对象的属性。
猜你喜欢
  • 2023-04-02
  • 2023-03-21
  • 2013-10-06
  • 1970-01-01
  • 2017-09-15
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
相关资源
最近更新 更多