标题可能不是很解释(我尝试过,对不起)。
场景
我具有Computer
和Software
的多对多关系,因此具有联接模型ComputerSoftware
。我想在创建新计算机时能够将计算机与当前可用软件列表中的许多软件连接起来。这是一些代码来解释:
class Computer < ApplicationRecord
has_many :computer_softwares
has_many :computers, through: :computer_softwares
accepts_nested_attributes_for :softwares
end
class Software < ApplicationRecord
has_many :computer_softwares
has_many :softwares, through: :computer_softwares
end
class ComputerSoftware < ApplicationRecord
belongs_to :software
belongs_to :computer
end
我的控制器看起来像这样:
class ComputersController < ApplicationController
before_action :set_computer, only: %i[show edit update destroy]
before_action :set_softwares, only: :new
def index
@computers = Computer.all
end
def show; end
def new; end
def edit; end
def create
@computer = Computer.new(computer_params)
# do something to save the associated softwares...
# params.require(:computer).permit(:softwares) <= unpermitted param
if @computer.save
redirect_to computers_path, notice: 'Successfully created.'
else
render :new
end
end
def update
if @computer.update(computer_params)
redirect_to @computer, notice: 'Successfully updated.'
else
render :edit
end
end
def destroy
@computer.destroy
redirect_to computers_url, notice: 'Successfully destroyed.'
end
private
def set_computer
@computer = Computer.find(params[:id])
end
def computer_params
params.require(:computer).permit(:name)
end
def set_softwares
@softwares = Software.all
end
end
关联正常,我在rails console
中进行了测试,一切都很好。但是现在我来创建一个表格,例如Computer
:
app/views/computers/_form.html.erb
<%= form_with(model: computer, local: true) do |form| %>
<div>
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<%= form.collection_check_boxes :softwares, @softwares, :id, :name, include_hidden: false do |field| %>
<%= field.check_box %>
<%= field.text %>
<% end %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
我已经尝试过对此进行一些修改,但是由于softwares
的原因,我总是会在视图中出现一些错误,或者即使在accepts_nested_attributes_for :softwares
模型中设置了Computer
的情况下,也不允许在控制器中使用参数。
无奈之下,我选择尝试使复选框完全不属于computer
,并仅在控制器中通过关联创建联接。这对于new
有用,但随后在edit
中失败了。任何帮助,不胜感激。
Edit 1(应jvillian的要求)
我尝试过的强大参数如下:
def computer_params
required_params.permit(computer_softwares_attributes: [:software_id])
end
def required_params
params.require(:computer)
end
但是这会导致服务器日志中出现unpermitted params
消息(结果是computer_params[:computer_softwares]
为nil
)。在服务器日志中,它看起来如下所示:
Unpermitted parameters: :name, :computer_softwares
<ActionController::Parameters {} permitted: true>
编辑2
[不知道为什么我较早就没想到-但是删除了严格的要求,只是执行params[:computer][:softwares]
实际上效果很好。真正剩下的唯一问题是我如何使用强参数来达到相同的结果,否则将很容易受到攻击。
您需要允许computer_params
中的那些嵌套属性:
def computer_params
params.require(:computer).permit(:name, software: [:something, :something_else])
end
您想为嵌套软件模型允许的任何字段都必须放在该software
键内