在过去的几天里,我在谷歌上搜索并尝试了我能想到的一切,以解决has_and_belongs_to_many
关系的一个相对简单的问题。
我成功地使用HABTM关系提交了一个关系值。这是示例代码:
型号:
class Livre < ActiveRecord::Base
has_and_belongs_to_many : auteurs
end
class Auteur < ActiveRecord::Base
has_and_belongs_to_many :livres
end
控制器:
def new
@livre = Livre.new
@auteurs = Auteur.all
end
def create
@livre = Livre.new(livre_params)
if @livre.save
redirect_to [:admin, @livre]
else
render 'new'
end
end
private
def livre_params
params.require(:livre).permit(:name, :auteur_ids)
end
视图:
<% f.label :auteur %><br>
<% f.collection_select(:auteur_ids, @auteurs, :id, :name) %>
已发布参数:
{"utf8"=>"✓",
"authenticity_token"=>"mAXUm7MRDgJgCH00VPb9bpgC+y/iOfxBjXSazcthWYs=",
"livre"=>{"name"=>"sdfsdfd",
"auteur_ids"=>"3"},
"commit"=>"Create Livre"}
但是,当我尝试将"multiple true"添加到视图的collection_select
辅助对象时,(现在是multiple)关系将不再保存。样本代码:
(型号和控制器不变)
视图:
<% f.label :auteur %><br>
<% f.collection_select(:auteur_ids, @auteurs, :id, :name, {}, {:multiple => true}) %>
已发布参数:
{"utf8"=>"✓",
"authenticity_token"=>"mAXUm7MRDgJgCH00VPb9bpgC+y/iOfxBjXSazcthWYs=",
"livre"=>{"name"=>"sdfsdf",
"auteur_ids"=>["1",
"5",
"3"]},
"commit"=>"Create Livre"}
正如您所看到的,"auter_ids"的params现在是一个数组。这是唯一的区别。
我做错了什么?
澄清一下:这两段代码都可以向livres
db表添加新记录,但只有第一段代码能够向auteurs_livres
db表添加适当的记录。第二个简单地不向auteurs_livres
中插入任何内容。
(我在ruby 1.9.3p194和rails 4.0.1上运行)
谢谢!
回答
对于那些陷入同样问题的优秀人士,以下是答案:
编辑控制器并将允许的参数从:auteur_ids
更改为{:auteur_ids => []}
params.require(:livre).permit(:name, {:auteur_ids => []})
现在它可以工作了:)
对于那些遇到同样问题的优秀人士,以下是答案:
编辑控制器并将允许的参数从:auteur_ids
更改为{:auteur_ids => []}
params.require(:livre).permit(:name, {:auteur_ids => []})
现在它可以工作了:)
您之所以制定了解决方案,是因为Rails现在希望auteur_ids
是一个数组,而不是单个项。这意味着,它不只是将单个实体传递给模型,而是将参数打包为[0][1][2]
等,这就是您现在可以提交HABTM记录的方式
Rails还有一种更多的方法可以做到这一点,那就是使用accepts_nested_attributes_for
。这看起来会有更多的工作,但它会让你的系统干涸,也会确保常规配置:
型号
class Livre < ActiveRecord::Base
has_and_belongs_to_many : auteurs
accepts_nested_attributes_for :auteurs
end
class Auteur < ActiveRecord::Base
has_and_belongs_to_many :livres
end
控制器
def new
@livre = Livre.new
@livre.auteurs.build
@auteurs = Auteur.all
end
def create
@livre = Livre.new(livre_params)
if @livre.save
redirect_to [:admin, @livre]
else
render 'new'
end
end
private
def livre_params
params.require(:livre).permit(:name, auteur_attributes: [:auteur_id])
end
表单
<%= form_for @livre do |f| %>
<%= f.text_field :your_current_vars %>
<%= f.fields_for :auteurs do |a| %>
<%= a.collection_select(:auteur_id, @auteurs, :id, :name, {}) %>
<% end %>
<% end %>
这将为您提交auter_id(并自动关联HABTM模型中的livre_id
外键。目前,这只会提交在new
操作中构建的对象数量——因此,为了添加更多项目,您必须构建更多