出于某种原因。
我想删除并创建而不是嵌套表单的UPDATE。
正常更新正常工作
def update
@post = Post.find(params[:id])
ActiveRecord::Base.transaction do
@post.update!(update_params)
end
rescue ActiveRecord::RecordInvalid
puts "ERROR"
end
我想改为喜欢(不工作)
def update
@post = Post.find(params[:id])
ActiveRecord::Base.transaction do
@post.attributes = update_params
@post.post_categories.each do |pc|
if pc.changed?
pc.mark_for_destruction
end
end
@post.save!
@post.attributes = update_params
@post.save!
end
rescue ActiveRecord::RecordInvalid
puts "ERROR"
end
这是所有代码的正常更新版本 https://github.com/shingo-nakanishi/workout_rails/tree/v5.0
发表
class Post < ActiveRecord::Base
has_many :post_categories, inverse_of: :post
accepts_nested_attributes_for :post_categories,
allow_destroy: true,
reject_if: :is_reject
private
def is_reject(attributes)
is_exist = attributes[:id].present?
is_empty = attributes[:post_category_id].blank?
attributes.merge!(_destroy: 1) if is_exist and is_empty
!is_exist and is_empty
end
end
PostCategory
class PostCategory < ActiveRecord::Base
belongs_to :post, inverse_of: :post_categories
belongs_to :post_category_master
end
PostCategoryMaster
class PostCategoryMaster < ActiveRecord::Base
end
PostsController
class PostsController < ApplicationController
def new
@post = Post.new
@post.post_categories.build
end
def create
@post = Post.new(create_params)
@post.save!
rescue ActiveRecord::RecordInvalid
puts "ERROR"
end
def edit
@post = Post.find(params[:id])
unless @post.post_categories.present?
@post.post_categories.build
end
end
def update
@post = Post.find(params[:id])
ActiveRecord::Base.transaction do
@post.attributes = update_params
@post.post_categories.each do |pc|
if pc.changed?
pc.mark_for_destruction
end
end
@post.save!
@post.attributes = update_params
@post.save!
end
rescue ActiveRecord::RecordInvalid
puts "ERROR"
end
private
def create_params
params.require(:post).permit(:description, post_categories_attributes: [:post_category_id])
end
def update_params
params.require(:post).permit(:description, post_categories_attributes: [:id, :post_category_id])
end
end
查看/帖/ edit.html.erb
<%= form_for @post do |f| %>
<%= f.label :description %><%= f.text_field :description %><br/>
<%= f.fields_for :post_categories do |b| %>
<%= b.label :post_category_id %>
<%= b.collection_select :post_category_id,
PostCategoryMaster.all,
:id,
:name,
multiple: true,
include_blank: 'none',
prompt: 'please select' %>
<% end -%>
<%= f.submit %>
<% end %>
请参阅上文 PostsController #update
使用 mark_for_destruction ,然后分配相同的update_params。
获取错误
对于ID为36的帖子,找不到ID = 31的PostCategory
如何删除和创建嵌套表单的UPDATE而不是UPDATE。
答案 0 :(得分:0)
我认为你基本上对嵌套属性如何工作感到困惑。
嵌套属性允许您在以下时创建:post_categories:
POST "/posts"
并使用以下内容更新帖子和类别:
UPDATE "/posts/:id"
这意味着在现有PostCategories
上添加/删除Post
将始终使用update
(PUT / PATCH)。
但是当你使用collection_select
时,它根本不使用嵌套属性。相反,它会创建一个传递给模型*_ids=
setter的id数组。在模型上设置post.post_category_ids= [1]
时,它会删除/添加关联。
请注意,post_category_ids
为复数形式。但是您的表单不正确,因为它不应该在f.fields_for :post_categories
块内。
<%= form_for @post do |f| %>
<%= f.label :description %><%= f.text_field :description %><br/>
<%= b.label :post_category_ids %>
<%= b.collection_select :post_category_ids,
PostCategoryMaster.all,
:id,
:name,
multiple: true,
include_blank: 'none',
prompt: 'please select'
%>
<%= f.submit %>
<% end %>
private
def create_params
params.require(:post).permit(:description, post_category_ids: [])
end
def update_params
params.require(:post).permit(:description, post_category_ids: [])
end
创建使用嵌套属性进行添加/删除的表单元素要复杂得多。
如果您想使用POST / DELETE谓词对相关类别进行操作,则必须创建其他路径和控制器。
请注意,accept_nested_attributes在这种情况下毫无意义,因为它甚至不会被使用。
resources :posts do
resources :categories
end
然后你会用
POST "/posts/:post_id/categories" # to create a post.
DELETE "/posts/:post_id/categories/:id" # to destroy a post.
您必须为每个类别创建一个表单(或使用button_for)。
<%= @categories.each do |c| %>
<%= button_to "Delete", post_categories_path(post_id: c.post, id: c), method: :delete, confirm: "Are you sure?" %>
<% end %>