创建一个自定义的多对多关联 - Ruby on Rails

时间:2016-04-02 13:05:31

标签: mysql ruby-on-rails associations

我正在尝试制作一个存储FIFA游戏的应用程序。

我在设置正确的关联方面遇到了一些麻烦。

此时我有2个模型,用户和游戏。

SCHEMA:

ActiveRecord::Schema.define(version: 20160402112419) do

  create_table "games", force: :cascade do |t|
    t.integer  "home_team_user_id"
    t.integer  "away_team_user_id"
    t.string   "home_score"
    t.string   "away_score"
    t.integer  "winner_id"
    t.integer  "loser_id"
    t.datetime "created_at",        null: false
    t.datetime "updated_at",        null: false
  end

  create_table "games_users", id: false, force: :cascade do |t|
    t.integer "user_id"
    t.integer "game_id"
  end

  add_index "games_users", ["user_id", "game_id"], name: "index_games_users_on_user_id_and_game_id"

  create_table "users", force: :cascade do |t|
    t.string   "username"
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

模型:

class Game < ActiveRecord::Base
    has_and_belongs_to_many :users
end

class User < ActiveRecord::Base
    has_and_belongs_to_many :games
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

正如您所看到的,“游戏”表格有2个相应的ID:

  • home_team_user_id
  • away_team_user_id

这些将存储Users表中的user_id,这是计算与分数对应的获胜者所必需的。

控制台结果:

irb(main):001:0> Game.last
  Game Load (0.0ms)  SELECT  "games".* FROM "games"  ORDER BY "games"."id" DESC LIMIT 1
=> #<Game id: 1, home_team_user_id: 1, away_team_user_id: 1, home_score: "1", away_score: "2", winner_id: 1, loser_id: 1, created_at: "2016-04-02 12:27:26", updated_at: "2016-04-02 12:27:26">
irb(main):002:0> game = Game.find(1)
  Game Load (0.5ms)  SELECT  "games".* FROM "games" WHERE "games"."id" = ? LIMIT 1  [["id", 1]]
=> #<Game id: 1, home_team_user_id: 1, away_team_user_id: 1, home_score: "1", away_score: "2", winner_id: 1, loser_id: 1, created_at: "2016-04-02 12:27:26", updated_at: "2016-04-02 12:27:26">
irb(main):003:0> game.users
  User Load (0.5ms)  SELECT "users".* FROM "users" INNER JOIN "games_users" ON "users"."id" = "games_users"."user_id" WHERE "games_users"."game_id" = ?  [["game_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy []>

我现在想的是User.id需要链接到Games表中每个对应的id。

我该如何设置?我是否需要使用has_many :through关联?

更新:

可能就像这样简单:

class User < ActiveRecord::Base

    has_many :games, :foreign_key => "home_team_user_id"
    has_many :games, :foreign_key => "away_team_user_id"


  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end



class Game < ActiveRecord::Base

    belongs_to :user, :foreign_key => "home_team_user_id"
    belongs_to :user, :foreign_key => "away_team_user_id"
end

因为实际上用户有很多游戏,但在那个游戏中他只有一个团队,即主队或客队。在这个逻辑中,我将user_id分配给一个自定义外部字段。

1 个答案:

答案 0 :(得分:1)

你可以这样做:

class User < ActiveRecord::Base
  has_many :home_games,    class_name: 'Game', foreign_key: 'home_team_user_id'
  has_many :away_games, class_name: 'Task', foreign_key: 'away_team_user_id'
end

class Game < ActiveRecord::Base
  belongs_to :home_user,    class_name: "User", foreign_key: "home_team_user_id"
  belongs_to :away_user, class_name: "User", foreign_key: "away_team_user_id"
  # Rails anticipate foreign keys itself so, addig `foreign_keys` is not
  # necessary in this class as we've already mentioned `belongs_to :home_user`
end