我有一個表“電影”,其架構如下所示:
create_table "films", force: :cascade do |t|
t.integer "tmdb_id", null: false
t.string "language_iso_639_1", null: false
t.string "title", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["tmdb_id", "language_iso_639_1"], name: "index_films_on_tmdb_id_and_language_iso_639_1", unique: true
end
如您所見,tmdb_id 本身并不是唯一的,只有 tmdb_id 和 language_iso_639_1 的組合。到目前為止,這按預期作業,讓我創建如下記錄:
[#<Film:0x0000000108156630
id: 1,
tmdb_id: 12,
language_iso_639_1: "en",
title: "Finding Nemo",
created_at: Fri, 15 Apr 2022 14:58:43.128785000 UTC 00:00,
updated_at: Fri, 15 Apr 2022 14:58:43.128785000 UTC 00:00>,
#<Film:0x00000001081564f0
id: 2,
tmdb_id: 12,
language_iso_639_1: "de",
title: "Findet Nemo",
created_at: Fri, 15 Apr 2022 14:58:52.563142000 UTC 00:00,
updated_at: Fri, 15 Apr 2022 14:58:52.563142000 UTC 00:00>,
#<Film:0x0000000108156428
id: 3,
tmdb_id: 12,
language_iso_639_1: "fr",
title: "Le Monde de Nemo",
created_at: Fri, 15 Apr 2022 14:59:03.318667000 UTC 00:00,
updated_at: Fri, 15 Apr 2022 14:59:03.318667000 UTC 00:00>]
現在我想創建另一個表“film_backdrops”來保存特定電影的背景影像。這些影像對于不同的語言沒有區別,因此只有 tmdb_id 很重要。
我的(可能要修改)這個表的方案目前看起來像這樣:
create_table "film_backdrops", force: :cascade do |t|
t.integer "tmdb_id", null: false
t.string "file_path", null: false
t.float "vote_average"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
一個條目看起來像這樣,例如:
#<FilmBackdrop:0x0000000108a3e798
id: 1,
tmdb_id: 12,
file_path: "/bla/bla/image.png",
vote_average: 9.8,
created_at: Fri, 15 Apr 2022 15:00:59.635324000 UTC 00:00,
updated_at: Fri, 15 Apr 2022 15:00:59.635324000 UTC 00:00>
我想鏈接這兩個表,以便為具有相同 tmdb_id 且與 language_iso_639_1 欄位無關的電影回傳相同的 FilmBackdrop 記錄,如下所示:
Film.find_by(tmdb_id: 12, language_iso_639_1: "en").film_backdrops # => #<FilmBackdrop:0x0000000107b445d0
Film.find(tmdb_id: 12, language_iso_639_1: "de").film_backdrops # => #<FilmBackdrop:0x0000000107b445d0
Film.find(tmdb_id: 12, language_iso_639_1: "fr").film_backdrops # => #<FilmBackdrop:0x0000000107b445d0
反過來也應該有效:
FilmBackdrop.find(1).films # => #<Film:0x00000001077cd348, #<Film:0x00000001077cd280 , #<Film:0x00000001077cd1b8
由于我不需要 Film 的主鍵“id”,而且僅 Film 的“tmdb_id”也不是唯一的,所以到目前為止我嘗試過的任何方法都沒有成功。
甚至可以在不創建第三個“中間”表的情況下完成它嗎?
uj5u.com熱心網友回復:
聽起來您缺少一個值tmdb_id是唯一鍵的模型。
這將has_many與Film,并且,我認為,has_many與FilmBackdrop。
然后Film并FilmBackdrop會彼此has_many通過這個模型。
uj5u.com熱心網友回復:
假設您提供的架構沒有更改,您唯一需要做的就是在您的關聯中指定foreign_key和primary_key選項:
class Film
has_many :film_backdrops, foreign_key: :tmdb_id, primary_key: :tmdb_id
end
class FilmBackdrop
has_many :films, foreign_key: :tmdb_id, primary_key: :tmdb_id
end
請注意,雖然這可以滿足您的目的,但它在 Rails 中是非標準的。inverse因此,將不支持某些功能,例如關聯。
uj5u.com熱心網友回復:
我猜你在這里做的是本地化電影,這個解決方案感覺非常落后和過于復雜。
Rails 并沒有真正做復合主鍵/外鍵,因為這不是資料庫中廣泛支持的東西。有一個用于復合主鍵的 gem,但它是建立在 hacking ActiveRecord 內部的,所以我會考慮這是否是你真的想在你的應用程式上施加的東西。
我會這樣做:
class Film
has_many :film_localizations
has_many :film_backdrops
end
# rails g model film_localization film:belongs_to language_iso_639_1:string title:string
class FilmLocalization
belongs_to :film
end
如果您想使用外部派生的 UUID 而不是自動遞增的整數或為電影表生成的 UUID,那很好。
但是您的模型應該有一個唯一的主鍵,其他表可以使用它來參考它,否則當您與整個 ORM / 約定作斗爭時,您將遇到非常困難的時期。
FilmLocalization如果您希望 a表現得像 a ,則可以使用委托Film。
還有現成的解決方案可用于翻譯模型資料,例如Mobility。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/460264.html
