>我有以下模型:Game
、HighSchoolTeam
和ClubTeam
。我希望Game
两个有一个team_one
和一个team_two
字段,每个字段都指一个HighSchoolTeam
或一个ClubTeam
。
在HighSchoolTeam
和ClubTeam
我有has_many :games, as: :teamable
.在Game
我想做类似的事情...
class Game < ApplicationRecord
belongs_to :team_one, polymorphic: true, class_name: "Teamable"
belongs_to :team_two, polymorphic: true, class_name: "Teamable"
end
。但是class_name: "Teamable
部分似乎不起作用。
编辑:
模式.rb
ActiveRecord::Schema.define(version: 2019_12_24_011346) do
...
create_table "club_teams", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "fields", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "games", force: :cascade do |t|
t.bigint "tournament_id", null: false
t.string "team_one_type", null: false
t.bigint "team_one_id", null: false
t.string "team_two_type", null: false
t.bigint "team_two_id", null: false
t.bigint "field_id", null: false
t.date "date"
t.datetime "start_time"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["field_id"], name: "index_games_on_field_id"
t.index ["team_one_type", "team_one_id"], name: "index_games_on_team_one_type_and_team_one_id"
t.index ["team_two_type", "team_two_id"], name: "index_games_on_team_two_type_and_team_two_id"
t.index ["tournament_id"], name: "index_games_on_tournament_id"
end
create_table "high_school_teams", force: :cascade do |t|
t.string "school_name"
t.string "team_name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "tournaments", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
add_foreign_key "games", "fields"
add_foreign_key "games", "tournaments"
end
游戏.rb
class Game < ApplicationRecord
belongs_to :tournament
belongs_to :team_one, polymorphic: true
belongs_to :team_two, polymorphic: true
belongs_to :field, optional: true
end
high_school_team.rb
class HighSchoolTeam < ApplicationRecord
has_many :players
has_many :games, as: :teamable, dependent: :destroy
def name
self.school_name
end
end
club_team.rb
class ClubTeam < ApplicationRecord
has_many :players
has_many :games, as: :teamable, dependent: :destroy
end
控制台输出
code/scout-db [master●] » rails c --sandbox
Running via Spring preloader in process 48525
Loading development environment in sandbox (Rails 6.0.1)
Any modifications you make will be rolled back on exit
WARNING: This version of ruby is included in macOS for compatibility with legacy software.
In future versions of macOS the ruby runtime will not be available by
default, and may require you to install an additional package.
irb(main):001:0> game = Game.new({ team_one_id: "high-school-team-2", team_one_type: "HighSchoolTeam", team_two_id: "club-team-2", team_two_type: "ClubTeam" })
(0.2ms) BEGIN
=> #<Game id: nil, tournament_id: nil, team_one_type: "HighSchoolTeam", team_one_id: 0, team_two_type: "ClubTeam", team_two_id: 0, field_id: nil, date: nil, start_time: nil, created_at: nil, updated_at: nil>
irb(main):002:0> game.team_one_id
=> 0
irb(main):003:0> game.save
(0.3ms) SAVEPOINT active_record_1
HighSchoolTeam Load (0.4ms) SELECT "high_school_teams".* FROM "high_school_teams" WHERE "high_school_teams"."id" = $1 LIMIT $2 [["id", 0], ["LIMIT", 1]]
ClubTeam Load (0.3ms) SELECT "club_teams".* FROM "club_teams" WHERE "club_teams"."id" = $1 LIMIT $2 [["id", 0], ["LIMIT", 1]]
(0.4ms) ROLLBACK TO SAVEPOINT active_record_1
=> false
irb(main):004:0> game.errors.full_messages.inspect
=> "["Tournament must exist", "Team one must exist", "Team two must exist"]"
(2, Syosset, Braves, 2019-12-31 01:07:41.367913, 2019-12-31 01:07:41.367913)
存在于high_school_teams
表中,(2, Foobars, 2019-12-31 01:07:52.697821, 2019-12-31 01:07:52.697821)
存在于club_teams
表中。
当然class_name: "Teamable"
不起作用,因为多态关联的全部要点是关联的类(更重要的是目标表(是动态的。它也不需要。
多态关联使用单独的association_name_type
字符串列,其中包含与其关联的类名。
给定以下数据:
| id | team_one_id | team_one_type # ...
----------------------------------
1 | 1 | "HighSchoolTeam"
2 | 2 | "ClubTeam"
3 | 3 | "HighSchoolTeam"
当你这样做时Game.find(1).team_one
Rails知道使用HighSchoolTeam
类并加入high_school_teams
表。但是它需要先拉出行才能建立连接,当然,您的数据库对关系一无所知,也不会维护引用完整性。
所以你所需要的只是:
class Game < ApplicationRecord
belongs_to :team_one, polymorphic: true
belongs_to :team_two, polymorphic: true
end
并确保games
表上有team_one_type
和team_two_type
字符串列。
class_name
应该与数据库中的类名匹配。