Rails-通过记录在has_many上设置其他属性 [英] Rails - Set additional attribute on has_many through record
问题描述
使用Rails 6.0.3.3和ruby'2.6.0'.
Using Rails 6.0.3.3 and ruby '2.6.0'.
我通过 has_many通过
关系连接了这3个模型.
I have these 3 models connected via a has_many through
relation.
class Recipe < ApplicationRecord
has_many :layers
has_many :glazes, through: :layers
end
class Glaze < ApplicationRecord
has_many :layers
has_many :recipes, through: :layers
end
class Layer < ApplicationRecord
belongs_to :recipe
belongs_to :glaze
# there is a column named "coat_type" here that I would like to set
end
一切对于创建新的 Recipe
都非常有用,并且可以自动创建其相关的 Layer
记录.但是现在,我想在创建 Layer
记录时在其上设置一个 coat_type
属性,但似乎无法弄清楚该如何做.
Everything is working great for creating a new Recipe
and it automagically creating its related Layer
record. But now I would like to also set a coat_type
attribute on the Layer
record when it's created, but I can't seem to figure out how I could do something like that.
表单视图部分
= form_with model: recipe, local: true do |form|
%p
= form.label :name
%br
= form.text_field :name
%p
= form.label :description
%br
= form.text_area :description
.recipe-glaze
= form.collection_select(:glaze_id, Glaze.all, :id, :name, { prompt: "Select Glaze" }, { name: 'recipe[glaze_ids][]' })
.recipe-glaze
= form.collection_select(:glaze_id, Glaze.all, :id, :name, { prompt: "Select Glaze" }, { name: 'recipe[glaze_ids][]' })
%p
= form.submit
控制器创建动作(和强大的参数acton)
The Controller Create Action (and strong params acton)
def create
@recipe = Recipe.new(recipe_params)
if @recipe.save
redirect_to @recipe
else
render 'new'
end
end
private
def recipe_params
params.require(:recipe).permit(:name, :description, glaze_ids: [])
end
理想情况下,我将能够在表单中添加另一个选择框,并且用户将使用该选择框设置将要创建的 Layer
记录的 coat_type
.但是我无法弄清楚如何将其传递给控制器并使它知道如何处理该值.
Ideally, I would be able to add another select box in the form and the user would use that to set the coat_type
of the Layer
record that will be created. But I can't figure out how I could pass that into the controller and have it know what to do with that value.
这是否可行,还是我处理方法不正确?
Is this something that is possible, or am I approaching this incorrectly?
推荐答案
所以我实际上最终跌倒了"; cocoon"gem 感谢此评论.通过遵循茧"的设置说明,我可以调整代码以完成所需的工作.
So I actually ended up stumbling upon the "cocoon" gem thanks to this comment. By following the setup instructions for "cocoon", I was able to tweak my code to do what I needed.
我的 Recipe
模型更改为此:::
My Recipe
model changed to this ::
class Recipe < ApplicationRecord
has_many :layers, inverse_of: :recipe
has_many :glazes, through: :layers
accepts_nested_attributes_for :layers, reject_if: :all_blank, allow_destroy: true
end
我控制器的强大params动作更改为:::
My controller's strong params action changed to this ::
private
def recipe_params
params.require(:recipe).permit(:name, :description, layers_attributes: [:id, :glaze_id, :coat_type, :_destroy])
end
我的表单视图部分更改为::
My form view partial changed to ::
- if recipe.errors.any?
= render partial: 'errors', locals: { recipe: recipe }
%p
= form.label :name
%br
= form.text_field :name
%p
= form.label :description
%br
= form.text_area :description
%h3 Layers
#layers
= form.fields_for :layers do |layer|
= render 'layer_fields', f: layer
.links
= link_to_add_association 'add layer', form, :layers
%p
= form.submit
和"layer_fields"表单中引用的部分内容看起来像这样::
and the "layer_fields" partial referenced in the form looks like this ::
.nested-fields
.field
= f.label :glaze_id
%br
= f.collection_select(:glaze_id, Glaze.all, :id, :name, { prompt: "Select Glaze" } )
.field
= f.label :coat_type
%br
= f.text_field :coat_type
= link_to_remove_association 'remove layer', f
使用"Cocoon"进行更改.宝石,我能够完成我所需要的.希望这对以后的人有所帮助.
Making those changes using the "Cocoon" gem, I was able to accomplish what I needed. Hopefully this helps someone else in the future.
这篇关于Rails-通过记录在has_many上设置其他属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!