İç içe yerleştirilmiş öznitelikleri çoktan çoğa kaydederken hata olmalıdır
Rails 6'da çoktan çoğa ilişkilendirme yoluyla iç içe geçmiş kayıtları kaydetmeye çalışılıyor, ancak "etiket mevcut olmalıdır" hatası alınıyor. Etiket, Gönderiler ve Etiketler (çoktan çoğa) arasındaki çapraz referans tablosu olan post_tags için bir ebeveyndir. Yapmak istediğim, yeni bir gönderi oluşturulduğunda, gönderi formunda seçilen etiketlerle ilgili post_tag kayıtlarını kaydetmek. İlgili bazı gönderilere baktım: burada ve burada ve ters_of, otomatik kaydetme: doğru ve isteğe bağlı: doğru kullanmayı denedim, ancak bunlar işe yaramıyor gibi görünüyor.
İşte sahip olduğum şey:
Modeller
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
Kontrolcü
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
Form
<%= f.fields_for :post_tags do |builder| %>
<%= builder.collection_check_boxes :tag_id, Tag.top_used, :id, :name, include_hidden: false %>
<% end %>
Hata
(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):
Yanıtlar
Açıkça "birleştirme modeli" örnekleri oluşturmanız gerekmez. tag_ids=
Oluşturulan ayarlayıcıya bir dizi geçirmeniz yeterlidir 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 %>
Denetleyiciniz şöyle görünmelidir:
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
Birleştirme modeli örneklerini oluşturmak için yuvalanmış öznitelikleri ve Fields_for'u kullanmak gerçekten yalnızca birleştirme modelinde ek bilgi depolamanız gerektiğinde gereklidir.