我的 rails 嵌套模型无法识别 _destroy 属性
My rails nested model isn't recognizing _destroy attribute
我有一个父模型(鸡尾酒)和一个子模型(剂量)。
我有一个嵌套表单,我希望能够在其中 create/delete 随时随地添加对象。
创建部分在强参数中没有 _destroy
属性的情况下工作,但是当我将 _destroy
添加到属性散列以便能够删除时,我得到错误 unknown attribute '_destroy' for Dose
.我不确定我哪里错了。
我还认为我的代码过于复杂,应该有一种比我正在做的更简单的方法来创建剂量(甚至需要 add_doses 方法吗?)。如果我能得到一些反馈,我将不胜感激。
鸡尾酒:
class Cocktail < ApplicationRecord
validates :name, uniqueness: true, presence: true
has_many :doses, dependent: :destroy
has_many :ingredients, through: :doses
accepts_nested_attributes_for :doses, allow_destroy: true
end
剂量:
class Dose < ApplicationRecord
validates :description, presence: true
belongs_to :cocktail
belongs_to :ingredient
validates :cocktail, uniqueness: { scope: :ingredient }
end
控制器:
class CocktailsController < ApplicationController
before_action :set_task, only: %i[show edit update]
def index
@cocktails = Cocktail.all
end
def show; end
def new
@cocktail = Cocktail.new
@cocktail.doses.build
end
def create
@cocktail = Cocktail.new(cocktail_params)
@cocktail.save
add_doses
redirect_to cocktails_path
end
def edit; end
def update
@cocktail.update(cocktail_params)
add_doses
redirect_to cocktail_path(@cocktail)
end
private
def set_task
@cocktail = Cocktail.find(params[:id])
end
def cocktail_params
params[:cocktail][:name] = params[:cocktail][:name].downcase.titleize
params.require(:cocktail).permit(:name)
end
def add_doses
@cocktail.doses.destroy_all
strong_params = params.require(:cocktail).permit(doses_attributes: [:description, :ingredient_id, :_destroy, :id])
params[:cocktail][:doses_attributes].each_key do |key|
@cocktail.doses.create(strong_params[:doses_attributes][key])
end
end
end
我的主窗体视图:
<%= simple_form_for @cocktail do |f| %>
<%= f.input :name, required: true %>
<%= f.nested_fields_for :doses do |dose| %>
<%= render '/cocktails/partials/doses_fields', f: dose %>
<% end %>
<div class="btn-group" role="group" aria-label="Basic example">
<%= link_to_add_association 'add dose', f, :doses, partial: '/cocktails/partials/doses_fields', class: "btn btn-secondary" %>
<%= f.button :submit, class: "btn btn-secondary" %>
</div>
<% end %>
我对添加新剂量的部分看法:
<div class='nested-fields'>
<div class="field">
<%= f.text_field :description %>
</div>
<%= f.association :ingredient, collection: Ingredient.all %>
<%= link_to_remove_association "remove dose", f %>
</div>
如果您还想指出我的代码的所有错误,请不要退缩,做最坏的;)
首先修复您的 #create
和 #update
方法,以便它们在您重定向之前检查记录是否实际保留!
然后将嵌套参数添加到白名单并取消 add_doses
方法,这是一种创造性但极其有缺陷的尝试,旨在复制嵌套属性提供的功能。
class CocktailsController < ApplicationController
before_action :set_cocktail, only: %i[show edit update]
def index
@cocktails = Cocktail.all
end
def show; end
def new
@cocktail = Cocktail.new
@cocktail.doses.build
end
def create
@cocktail = Cocktail.new(cocktail_params)
if @cocktail.save
redirect_to cocktails_path
else
render :new
end
end
def edit; end
def update
if @cocktail.update(cocktail_params)
redirect_to @cocktail
else
render :edit
end
end
private
def set_cocktail
@cocktail = Cocktail.find(params[:id])
end
def cocktail_params
# this should be done in the model
params[:cocktail][:name] = params[:cocktail][:name].downcase.titleize
params.require(:cocktail)
.permit(
:name,
doses_attributes: [
:id,
:_destroy,
:description,
:ingredient_id
]
)
end
end
如果您想让用户删除嵌套记录,只需创建一个复选框:
<div class='nested-fields'>
<div class="field">
<%= f.text_field :description %>
</div>
<%= f.association :ingredient, collection: Ingredient.all %>
<%= f.input :_destroy, as: :boolean, label: 'Remove' %>
</div>
您还需要修复您的验证:
class Dose < ApplicationRecord
validates :description, presence: true
belongs_to :cocktail
belongs_to :ingredient
validates :cocktail_id, uniqueness: { scope: :ingredient_id }
end
创建唯一性验证时,您需要将其设置为验证实际列而非关联的唯一性。
我有一个父模型(鸡尾酒)和一个子模型(剂量)。
我有一个嵌套表单,我希望能够在其中 create/delete 随时随地添加对象。
创建部分在强参数中没有 _destroy
属性的情况下工作,但是当我将 _destroy
添加到属性散列以便能够删除时,我得到错误 unknown attribute '_destroy' for Dose
.我不确定我哪里错了。
我还认为我的代码过于复杂,应该有一种比我正在做的更简单的方法来创建剂量(甚至需要 add_doses 方法吗?)。如果我能得到一些反馈,我将不胜感激。
鸡尾酒:
class Cocktail < ApplicationRecord
validates :name, uniqueness: true, presence: true
has_many :doses, dependent: :destroy
has_many :ingredients, through: :doses
accepts_nested_attributes_for :doses, allow_destroy: true
end
剂量:
class Dose < ApplicationRecord
validates :description, presence: true
belongs_to :cocktail
belongs_to :ingredient
validates :cocktail, uniqueness: { scope: :ingredient }
end
控制器:
class CocktailsController < ApplicationController
before_action :set_task, only: %i[show edit update]
def index
@cocktails = Cocktail.all
end
def show; end
def new
@cocktail = Cocktail.new
@cocktail.doses.build
end
def create
@cocktail = Cocktail.new(cocktail_params)
@cocktail.save
add_doses
redirect_to cocktails_path
end
def edit; end
def update
@cocktail.update(cocktail_params)
add_doses
redirect_to cocktail_path(@cocktail)
end
private
def set_task
@cocktail = Cocktail.find(params[:id])
end
def cocktail_params
params[:cocktail][:name] = params[:cocktail][:name].downcase.titleize
params.require(:cocktail).permit(:name)
end
def add_doses
@cocktail.doses.destroy_all
strong_params = params.require(:cocktail).permit(doses_attributes: [:description, :ingredient_id, :_destroy, :id])
params[:cocktail][:doses_attributes].each_key do |key|
@cocktail.doses.create(strong_params[:doses_attributes][key])
end
end
end
我的主窗体视图:
<%= simple_form_for @cocktail do |f| %>
<%= f.input :name, required: true %>
<%= f.nested_fields_for :doses do |dose| %>
<%= render '/cocktails/partials/doses_fields', f: dose %>
<% end %>
<div class="btn-group" role="group" aria-label="Basic example">
<%= link_to_add_association 'add dose', f, :doses, partial: '/cocktails/partials/doses_fields', class: "btn btn-secondary" %>
<%= f.button :submit, class: "btn btn-secondary" %>
</div>
<% end %>
我对添加新剂量的部分看法:
<div class='nested-fields'>
<div class="field">
<%= f.text_field :description %>
</div>
<%= f.association :ingredient, collection: Ingredient.all %>
<%= link_to_remove_association "remove dose", f %>
</div>
如果您还想指出我的代码的所有错误,请不要退缩,做最坏的;)
首先修复您的 #create
和 #update
方法,以便它们在您重定向之前检查记录是否实际保留!
然后将嵌套参数添加到白名单并取消 add_doses
方法,这是一种创造性但极其有缺陷的尝试,旨在复制嵌套属性提供的功能。
class CocktailsController < ApplicationController
before_action :set_cocktail, only: %i[show edit update]
def index
@cocktails = Cocktail.all
end
def show; end
def new
@cocktail = Cocktail.new
@cocktail.doses.build
end
def create
@cocktail = Cocktail.new(cocktail_params)
if @cocktail.save
redirect_to cocktails_path
else
render :new
end
end
def edit; end
def update
if @cocktail.update(cocktail_params)
redirect_to @cocktail
else
render :edit
end
end
private
def set_cocktail
@cocktail = Cocktail.find(params[:id])
end
def cocktail_params
# this should be done in the model
params[:cocktail][:name] = params[:cocktail][:name].downcase.titleize
params.require(:cocktail)
.permit(
:name,
doses_attributes: [
:id,
:_destroy,
:description,
:ingredient_id
]
)
end
end
如果您想让用户删除嵌套记录,只需创建一个复选框:
<div class='nested-fields'>
<div class="field">
<%= f.text_field :description %>
</div>
<%= f.association :ingredient, collection: Ingredient.all %>
<%= f.input :_destroy, as: :boolean, label: 'Remove' %>
</div>
您还需要修复您的验证:
class Dose < ApplicationRecord
validates :description, presence: true
belongs_to :cocktail
belongs_to :ingredient
validates :cocktail_id, uniqueness: { scope: :ingredient_id }
end
创建唯一性验证时,您需要将其设置为验证实际列而非关联的唯一性。