Полиморхи c ассоциации и has_many: путем генерации неправильных sql при попытке получить сквозные записи ассоциации, рельсы? - PullRequest
0 голосов
/ 03 апреля 2020

Я создал ассоциацию полиморфизма c Tagging, принадлежащую Micropost, а также Tag, чтобы проиллюстрировать

РЕДАКТИРОВАНИЕ Ошибка модели тегирования

class Tagging < ApplicationRecord

  belongs_to :tag, inverse_of: :taggings
  belongs_to :taggable, polymorphic: true
...

...

class Tag < ApplicationRecord

  has_many :taggings, as: :taggable, inverse_of: :taggable
  has_many :microposts, through: :taggings, source: :taggable, source_type: 'Micropost'
end

...

class Micropost < ApplicationRecord

  has_many :taggings, as: :taggable, inverse_of: :taggable
  has_many :tags, through: :taggings
...

Micropost, Tagging и Tag вместе прекрасно сохраняются и производятся

<Micropost id: 588, content: "<p>hi</p>", user_id: 1, created_at: "2020-04-02 10:00:34", updated_at: "2020-04-02 10:00:34", media_data: "", pics_count: nil, share_id: nil, commentable_id: nil, commentable_type: nil, gallery_id: nil>

...

<Tagging id: 8, taggable_type: "Micropost", taggable_id: 588, tag_id: 10, topic: "Travel", created_at: "2020-04-02 10:00:34", updated_at: "2020-04-02 10:00:34">

(этот тег уже существовал, поэтому нам не нужно было его создавать)

<Tag id: 10, name: "hello", created_at: "2020-04-01 08:39:36", updated_at: "2020-04-01 08:39:36">

Как вы можете видеть, наш идентификатор тегируемого источника и тип установлены правильно и наш tag_id сохранен правильно.

Но при попытке сделать Tag.find_by_name!("hello").microposts он возвращает пустой массив CollectionProxy.

Чтобы показать сгенерированный sql,

tag.microposts
Micropost Load (0.4ms)  SELECT "microposts".* FROM "microposts" INNER JOIN "taggings" ON "microposts"."id" = "taggings"."taggable_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."taggable_type" = $3 LIMIT $4  [["taggable_id", 10], ["taggable_type", "Tag"], ["taggable_type", "Micropost"], ["LIMIT", 11]]
=> <ActiveRecord::Associations::CollectionProxy []>

Он помещает tag_id в taggable_id, который на самом деле должен быть идентификатором микросообщения, поэтому он дает пустой массив.

Я подозреваю, что, как вы можете видеть в sql сгенерированный показывает ["taggable_type", "Tag"], ["taggable_type", "Micropost"], где Tag taggable_type не должно быть, но я не знаю, как от него избавиться.

РЕДАКТИРОВАТЬ Я добавляю для ясности схему

create_table "taggings", force: :cascade do |t|
  t.string "taggable_type"
  t.bigint "taggable_id"
  t.bigint "tag_id"
  t.string "topic"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
  t.index ["tag_id"], name: "index_taggings_on_tag_id"
  t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable_type_and_taggable_id"
  t.index ["topic"], name: "index_taggings_on_topic"
end

create_table "tags", force: :cascade do |t|
  t.string "name"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
  t.index ["name"], name: "index_tags_on_name"
end

Так потеряно.

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

изменить отношение в тегах

class Tagging < ApplicationRecord
  belongs_to :tag
  belongs_to :taggable, polymorphic: true
end

модель, имеющая столбец идентификатора другой модели, принадлежит этой модели.
Модель ER будет выглядеть следующим образом:

Micropost ---------> Tagging <------------ Tag
                   :taggable_type
                   :taggable_id
                   :tag_id
0 голосов
/ 03 апреля 2020

OK. Я понял, что определил в Tag модели, что

has_many :taggings, as: :taggable, inverse_of: :taggable

должно быть

has_many :taggings

, так как мы хотим, чтобы tags.taggings, а не tag.taggings как taggable, теперь будут запрашивать tag_id и для tag.microposts сгенерируйте правильное sql

Thnx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...