Создание многим-многим полиморфным ассоциациям - настоящее головокружение.Я уже провел день на этом, и у меня заканчивается энергия.
У меня есть две модели, Comment
и Project
.У меня третья модель Badge
.Пользователь может отреагировать на комментарий или проект, добавив значок.Комментарии и проекты будут reaction_targets
.
. Я думаю, я понимаю, как сделать полиморфную часть «многие ко многим».Проблема в том, что Comment
и Project
имеют разные типы идентификаторов.Comment
индексируется bigint
, тогда как Project
использует uuid
.
Моя таблица соединений называется reactions
, через которую Badge
указывает на reaction_targets
class Badge < ApplicationRecord
has_many :reactions
has_many :reaction_targets, through: :reactions
end
Каждая строка в таблице соединений указывает на значок и цель.
class CreateReactions < ActiveRecord::Migration[5.2]
def change
create_table :reactions do |t|
t.references :reaction_target, polymorphic: true
t.references :badge
end
end
end
Я установил, что ассоциация с reaction_target
является полиморфной.
class Reaction < ApplicationRecord
belongs_to :badge
belongs_to :reaction_target, polymorphic: true
end
Я указываю Comment
за столом соединения.
class Comment < ApplicationRecord
has_many :reactions, as: :reaction_target
has_many :badges, through: :reactions
end
Все работает правильно:
> b = Badge.first_or_create(name: 'badge')
> c = Comment.create
> c.badges
#=> []
> c.badges << b
#=> (0.2ms) SAVEPOINT active_record_1...
Однако все обстоит иначе, когда дело доходит до Project
.
Я устанавливаюсопоставление таким же образом:
class Project < ApplicationRecord
has_many :reactions
has_many :badges, through: :reactions
end
Но это не работает одинаково.
> b = Badge.first_or_create(name: 'badge')
> p = Project.create
> p.badges
#=> #<Badge::ActiveRecord_Associations_CollectionProxy:0x3fdc34cde54c>
Первое, что я вижу, это то, что #badges
возвращает объект, отличный от пустогомассив.
И когда я пытаюсь добавить значок в коллекцию, я получаю сообщение об ошибке:
(1.5ms) SAVEPOINT active_record_1
ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
: SAVEPOINT active_record_1
from /Users/123/.rvm/gems/ruby-2.6.0/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in `async_exec'
Caused by PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
from /Users/123/.rvm/gems/ruby-2.6.0/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in `async_exec'
Я вижу в schema.rb
, ожидается, что reaction_target_id
будетbigint
.
create_table "reactions", force: :cascade do |t|
t.string "reaction_target_type"
t.bigint "reaction_target_id"
t.bigint "badge_id"
t.index ["badge_id"], name: "index_reactions_on_badge_id"
t.index ["reaction_target_type", "reaction_target_id"], name: "index_reactions_on_reaction_target_type_and_reaction_target_id"
end
Я полагаю, что ошибка выше из-за этого.Можно ли установить полиморфные отношения с таблицами, которые имеют разные типы индексов?Если да, что мне нужно сделать, чтобы иметь возможность добавлять значки в проекты?Если нет, есть ли обходной путь?