Phải tồn tại lỗi khi lưu các thuộc tính lồng nhau qua nhiều đến nhiều

Jan 22 2021

Cố gắng lưu các bản ghi lồng nhau thông qua liên kết nhiều-nhiều trong Rails 6, nhưng nhận được lỗi "thẻ phải tồn tại". Thẻ là cha mẹ của post_tags là bảng tham chiếu chéo giữa Bài đăng và Thẻ (nhiều-nhiều). Điều tôi muốn làm là, khi một bài viết mới được tạo, hãy lưu các bản ghi post_tag liên quan đến các thẻ đã chọn trên biểu mẫu bài đăng. Tôi đã xem một số bài đăng liên quan: tại đây và tại đây , và đã thử sử dụng inverse_of, autosave: true và tùy chọn: true, nhưng những bài đăng này dường như không hoạt động.

Đây là những gì tôi có:

Mô hình

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

Contoller

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

Hình thức

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

lỗi

   (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):

Trả lời

1 max Jan 21 2021 at 23:36

Bạn không cần phải tạo ra các phiên bản "mô hình tham gia". Bạn chỉ cần truyền một mảng cho bộ tag_ids=định tuyến được tạo bởi has_many :tags, through: :post_tags.

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

Bộ điều khiển của bạn sẽ giống như sau:

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

Việc sử dụng các thuộc tính và fields_for lồng nhau để tạo các phiên bản mô hình nối chỉ thực sự cần thiết nếu bạn cần lưu trữ thông tin bổ sung trong mô hình nối.