通过多对多保存嵌套属性时必须存在错误



尝试在Rails 6中通过多对多关联保存嵌套记录,但获取"标签"必须存在;错误。Tag是post_tags的父类,post_tags是post和Tags(多对多)之间的交叉引用表。我要做的是,当创建一个新帖子时,保存与所选标签相关的post_tag记录在帖子表单上。我看了一些相关的帖子:这里和这里,并尝试使用inverse_of, autosave: true和optional: true,但这些似乎都不起作用。

我有:

模型
class Post < ApplicationRecord
has_many :post_tags, dependent: :destroy, inverse_of: :post, autosave: true
has_many :tags, through: :post_tags
end
class PostTag < ApplicationRecord
belongs_to :post
belongs_to :tag
end
class Tag < ApplicationRecord
has_many :post_tags, dependent: :destroy, inverse_of: :tag, autosave: true
has_many :posts, through: :post_tags
end

控制器

PostsController < ApplicationController
def new
@post = Post.new
@tags= Tag.all
@post.post_tags.build
end
def create
@post = Post.new(post_params)
@post.post_tags.build

if @post.save
...
end
end

private
def post_params
params.require(:post).permit(:title, :content, :user_id, post_tags_attributes: [tag_id: []])
end
end

形式
<%= f.fields_for :post_tags do |builder| %>
<%= builder.collection_check_boxes :tag_id, Tag.top_used, :id, :name, include_hidden: false %>
<% end %>

误差

(0.4ms)  ROLLBACK
↳ app/controllers/posts_controller.rb:229:in `create'
Completed 422 Unprocessable Entity in 41ms (ActiveRecord: 3.7ms | Allocations: 15178)


ActiveRecord::RecordInvalid (Validation failed: Post tags tag must exist):

您不需要显式地创建"连接模型"。实例。您只需要将一个数组传递给has_many :tags, through: :post_tags创建的tag_ids=setter。

<%= form_with(model: @post) %>
...
<div class="field">
<%= f.label :tag_ids %>
<%= f.collection_check_boxes :tag_ids, @tags, :id, :name %>
</div>
...
<% end %>

你的控制器应该看起来像:

PostsController < ApplicationController
def new
@post = Post.new
@tags = Tag.all
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post, status: :created
else
@tags = Tag.all
render :new
end
end

private
def post_params
params.require(:post)
.permit(:title, :content, :user_id, tag_ids: [])
end
end

使用嵌套属性和fields_for创建连接模型实例实际上只在需要在连接模型中存储额外信息时才需要。

最新更新