Rails:我如何绘制这个has_many,has_many关联?

时间:2017-07-10 17:38:36

标签: sql ruby-on-rails ruby activerecord model-associations

我目前正在为一个学生项目开发游戏。我正在围绕工程协会进行旋转。非常感谢社区的任何指导。

有3种型号/类:游戏,角色和行情。

游戏:

  • has_many字符(两个带引号的历史字符,你必须选择谁说的引用)
  • has_many引用(通过游戏)

字符:

  • has_many游戏(跟踪角色出现的游戏)
  • has_many Quotes

引用:

  • belongs_to Character
class Game < ActiveRecord::Base
  has_many :characters
  # Each game will have exactly 2 characters 
  # @game.characters will return the two characters
  has_many :quotes, through: :characters   
end

class Characters < ActiveRecord::Base
  has_many :games
  # @character.games will return all games the character appeared in
  has_many :quotes 
end

class Quote < ActiveRecord::Base
  belongs_to :character
end

这些是我创建的迁移:

class CreateGames < ActiveRecord::Migration[5.1]
  def change
    create_table :games do |t|
      t.text :game_state
    end
  end
end

class CreateCharacters < ActiveRecord::Migration[5.1]
  def change
    create_table :characters do |t|
      t.string :name
      t.string :title
    end
  end
end

class CreateQuotes < ActiveRecord::Migration[5.1]
  def change
    create_table :quotes do |t|
      t.string :content
      t.belongs_to :character, index: true
    end
  end
end

目标:

  1. 实例化包含两个字符的新游戏:@game = Game.new(@character1, @character2)
  2. @game.characters应该返回 这两个字。
  3. @character1.games应该返回所有游戏 这个角色出现在。
  4. @game.quotes应该全部归还 引用两个字符。
  5. 我的第一直觉是我需要has_many has_many关系的联接表并跟踪游戏。例如:。

    class GamesPlayed < ApplicationRecord
      belongs_to :character1
      belongs_to :character2
      belongs_to :game
    end
    

    如果您能提供任何指导或建议,请提前致谢。

2 个答案:

答案 0 :(得分:1)

要建模多对多关系,您可以使用依赖于连接表(无模型)的has_and_belongs_to_many或表示两个模型之间关系的模型。

我想知道你是否真的没有多对多的关系。请考虑一下:

class Game
  belongs_to :player_one, class_name: 'Player'
  belongs_to :player_two, class_name: 'Player'
  scope :for_player, ->(player) { where(player_one: player).or(where(player_two: player)) }

  def players
    Player.where(id: [player_one_id, player_two_id])
  end
end

class Player
  def games
    Game.for_player(self)
  end
end

# In use:
@game = Game.find(1)
@game.players
@player = Player.find(1)
@player.games
@player.games.where(created_at: 1.week.ago..Date.today)

请注意,game.playersplayer.games都会返回您可以在其他范围中使用的ActiveRecord_Relationhas_many上没有Player } model。

答案 1 :(得分:1)

你编写社团的方式,你并没有真正充实游戏与游戏之间的多对多关联。人物模型。基本上你需要一个连接表。

以最简单的形式,它看起来像:

class Game < ActiveRecord::Base
  has_many :game_character_joins
  has_many :characters, through: :game_character_joins
end

class Characters < ActiveRecord::Base
  has_many :game_character_joins
  has_many :games, through: :game_character_joins

end

class GameCharacterJoin < ActiveRecord::Base
  belongs_to :game
  belongs_to :character
end

联接表的迁移将是:

class CreateGameCharacterJoin < ActiveRecord::Migration[5.1]
  def change
    create_table :game_character_joins do |t|
      t.integer :game_id
      t.integer :character_id
    end
  end
end

这真的是我认为你问的更容易的部分。

然后,Quote和Game之间的关联对我来说有点奇怪。这是因为您需要获得单个游戏的所有行情吗?有很多方法可以模拟 - 为方便起见,引用和游戏之间关联的想法是什么?在我看来,引用是

  1. 需要角色和游戏,
  2. 由角色拥有
  3. 是关于游戏的
  4. 你如何处理这个问题确实成了一个偏好问题。根据关联的重要性,你可以在角色和角色之间有多对多的关系。引用和游戏之间的另一个引用,或者您可以依靠引用表中的其他数据来指定它所涉及的游戏。