在我的Rails 5.1应用程序中,我试图从头开始创建一个标记系统。
我希望Tags
成为多态has_many :through
关联,以便我可以标记多个模型。
目前我可以通过执行以下操作在控制台中创建Tag
(以及关联的Tagging
}:Note.last.tags.create(name: "example")
生成正确的SQL:
Note Load (0.2ms) SELECT "notes".* FROM "notes" ORDER BY "notes"."id" DESC LIMIT $1 [["LIMIT", 1]]
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO "tags" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "example"], ["created_at", "2017-10-21 14:41:43.961516"], ["updated_at", "2017-10-21 14:41:43.961516"]]
Note Load (0.3ms) SELECT "notes".* FROM "notes" WHERE "notes"."id" = $1 LIMIT $2 [["id", 4], ["LIMIT", 1]]
SQL (0.4ms) INSERT INTO "taggings" ("created_at", "updated_at", "tag_id", "taggable_id", "taggable_type") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", "2017-10-21 14:41:43.978286"], ["updated_at", "2017-10-21 14:41:43.978286"], ["tag_id", 9], ["taggable_id", 4], ["taggable_type", "Note"]]
但是当尝试通过我的表单创建Tag
及其关联时,它无法正常工作。我可以创建Tag
但不能创建Tagging
。
控制器/笔记/ tags_controller.rb
class Notes::TagsController < TagsController
before_action :set_taggable
private
def set_taggable
@taggable = Note.find(params[:note_id])
end
end
控制器/ tags_controller.rb
class TagsController < ApplicationController
before_action :authenticate_user!
def create
@tag = @taggable.tags.new(tag_params)
@tag.user_id = current_user.id
if @tag.save
redirect_to @taggable, success: "New tag created."
else
render :new
end
end
private
def tag_params
params.require(:tag).permit(:name)
end
end
的routes.rb
...
resources :notes, except: [:index] do
resources :tags, module: :notes
end
...
class Note < ApplicationRecord
belongs_to :notable, polymorphic: true
has_many :taggings, as: :taggable
has_many :tags, through: :taggings
end
class Tag < ApplicationRecord
has_many :taggings
has_many :taggables, through: :taggings
end
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :taggable, polymorphic: true
end
备注/ show.html.erb
<p><%= @note.body %></p>
<%= render partial: 'tags/tags', locals: { taggable: @note } %>
<%= render partial: 'tags/form', locals: { taggable: @note } %>
标记/ form.html.erb
<%= simple_form_for [taggable, Tag.new] do |f| %>
<%= f.input :name %>
<%= f.submit %>
<% end %>
答案 0 :(得分:0)
错误可能是由于默认情况下需要:标记关联而未保存标记。
尝试:
class Tagging < ApplicationRecord
belongs_to :tag, required: false
belongs_to :taggable, polymorphic: true
end
答案 1 :(得分:0)
您的方法存在基本缺陷,因为它会创建每个标记的重复项,而不是创建连接记录。它还增加了必要的复杂性,因为您必须为每个可标记资源创建嵌套控制器。
y_oracle
的唯一性验证不会失败,这表明您的应用程序存在缺陷 - 您应该在数据库中有一个唯一索引,并在模型中进行验证以避免重复。
这对于像评论这样的东西来说是一个非常好的方法,其中每个创建的记录应该是唯一的,但不适用于您链接到间接关联的情况。
要将现有标签分配给记录,您可以使用选择或复选框来传递ID数组:
tags.name
要创建新标记,您可以使用nested attributes或使用ajax向<%= form_for(@note) do |f| %>
# ...
<%= f.collection_checkboxes(:tags_ids, Tag.all, :id, :name) %>
<% end %>
发送POST请求并更新视图,以便标记最终位于复选框列表中。