Rails中有条件的has_many foreign_key?

时间:2012-02-28 22:20:41

标签: ruby-on-rails

我正在AI竞赛的网站上工作,你可以上传pacman或ghosts控制器,对它们进行评估,结果显示在网站上。

我有一个控制台表,叫做'座席':

class CreateAgents < ActiveRecord::Migration
  def change
    create_table :agents do |t|
      t.string :ctype # either 'pacman' or 'ghosts'
      t.references :user, :null => false
      ...
      t.timestamps
    end
    ...
  end
end

每个控制器属于一个用户,它们可以是两种类型:'pacman'或'ghosts'。

选择了两个控制器(一个pacman,一个ghost),他们玩游戏,游戏存储在数据库中:

class CreateGames < ActiveRecord::Migration
  def change
    create_table :games do |t|
      t.integer :pacman_agent_id
      t.integer :ghosts_agent_id
      t.integer :score
      t.timestamps
    end
    ... 
  end
end

当我想选择让我们说某个特定游戏的pacman代理时,我只是做了一个:

Game.first.pacman

使用belongs_to和相应的foreign_key:

class Game < ActiveRecord::Base
  belongs_to :pacman, class_name: 'Agent', foreign_key: 'pacman_agent_id'
  belongs_to :ghosts, class_name: 'Agent', foreign_key: 'ghosts_agent_id'
end

然而,我无法弄清楚如何为特定的代理人做相反的事情,即选择游戏。

我想做这样的事情:

Agent.first.games

因此,如果它是一个pacman或ghosts控制器,它将独立返回该特定控制器的游戏。

这是我尝试过的,但它不起作用:

class Agent < ActiveRecord::Base
  belongs_to :user
  has_many :games, foreign_key: (:ctype == 'pacman' ? 'pacman_agent_id' : 'ghosts_agent_id')
end

有什么想法吗?也许我的数据库设计不正确?

提前致谢!

2 个答案:

答案 0 :(得分:1)

  

有什么想法吗?也许我的数据库设计不正确?

是的,这绝对不正确!的xD

不是向一个模型添加两个id字段,而是应该使用多态关联,该关联也需要两个字段,但一个包含类型(模型名称),另一个包含id。你会在这里找到你需要的一切:

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

第一次有点复杂。 Theres还有一个关于这个主题的轨道广播(#154)。

答案 1 :(得分:0)

如果你不想使用多态关联,你可以使用它:)

class Game < ActiveRecord::Base
  belongs_to :pacman, class_name: 'Agent', foreign_key: :pacman_agent_id
  belongs_to :ghosts, class_name: 'Agent', foreign_key: :ghosts_agent_id
end


class Agent < ActiveRecord::Base
  belongs_to :user
  has_many :pacman_games, class_name: 'Game', foreign_key: :pacman_agent_id
  has_many :ghost_games, class_name: 'Game', foreign_key: :ghosts_agent_id
end

=> Agent.find_by_ctype('pacman').pacman_games
=> Agent.find_by_ctype('ghosts').ghost_games

=> Game.first.pacman
=> Game.first.ghosts