我应该如何在Rails 5中定义相同的两个模型之间的多个关系

时间:2018-02-02 21:03:18

标签: ruby-on-rails ruby ruby-on-rails-5

我有两种模式:

A Game用于跟踪纸牌游戏中的游戏状态。

管理卡片存储,洗牌,处理等方式的Deck

Game有许多不同的Decks,它必须立即跟踪。例如,两个独立的不同抽签甲板和一个丢弃甲板。

我对如何定义这些关系感到有点困惑。理想情况下,我会使用Game.draw_type_a Game.draw_type_b和Game.discard,我可以使用它们,并且每个都指向一个Deck。我已经尝试了has_one :through关系以及与定义的foreign_keys和类的传统一对一关系,但我还没有能够实现这一点。

我真的很想将所有套牌都保留为单一模型,因为它们的行为方式有很多重叠。我应该如何定义GameDeck模型中三种类型套牌之间的关系迁移应该如何实现它们?

2 个答案:

答案 0 :(得分:1)

我在Adj game中做了类似的事情。 这就是我要做的事情:

class Game < ApplicationRecord
  has_many :decks
  has_one :discard_deck, -> { where(deck_type: :discard) }, foreign_key: :game_id, class_name: 'Deck'
  has_one :draw_deck, -> { where(deck_type: :draw) }, foreign_key: :game_id, class_name: 'Deck'

  # example attributes:
  #   is_finished:boolean(default: false)

  def start
    # populate the decks
    draw_deck.create!
    discard_deck.create!

    # populate random cards to be a draw_deck
    total_draw_deck_cards = 50

    # pick 50 random cards. `RANDOM()` is for Postgresql; else check online
    random_cards = Card.order('RANDOM()').limit(total_draw_deck_cards)

    random_cards.each do |random_card|
      draw_deck.deck_cards.create!(card: random_card)
    end
  end

  def finish
    update!(is_finished: true)
  end

  # `deck` can be any deck_type. Add conditions here if you must for each different deck_type
  def draw_from(deck)
  # or if you have multiple players:
  # def draw_from(deck, player)
    deck_card = deck.deck_cards.first

    # then do something with this deck_card that you just drawed
    # i.e. you might want to put this into a "Hand" (Player), so you'll need a separate PlayerCard model
    # PlayerCard.create!(card: deck_card.card)

    # or if you have multiple players:
    # PlayerCard.create!(card: deck_card.card, player: player) 

    # then lastly remove this deck_card as you've already put it in your hand
    deck_card.destroy
  end
end

class Deck < ApplicationRecord
  enum deck_type: { draw: 0, discard: 1 }

  belongs_to :game
  has_many :deck_cards, -> { order(created_at: :desc) }
  has_many :cards, through: :deck_cards

  # example attributes:
  #   deck_type:integer
end

class DeckCard < ApplicationRecord
  belongs_to :deck
  belongs_to :card

  # example attributes:
  #   is_faced_down:boolean(default: true)
end

class Card < ApplicationRecord
  enum card_type: { monster: 0, magic: 1, trap: 2 }

  has_many :deck_cards
  has_many :decks, through: :deck_cards

  # example attributes:
  #   name:string
  #   image:string
  #   card_type:integer
end

答案 1 :(得分:0)

我会使用三表解决方案,即:游戏,套牌,game_decks(?)。

游戏有很多game_decks。 GameDecks有一个game_id,deck_id和deck_type(draw_type_a,draw_type_b等),所以它属于游戏,属于甲板 Decks有很多GameDecks。

此外,游戏通过GameDecks有很多Decks,而Decks通过GameDecks有很多游戏。

这使您可以执行game.decks来检索所有游戏套牌和game.decks.where(deck_type: :draw_type_a)所有游戏的draw_type_a套牌(这可以通过范围进一步细化)。

作为旁注,我会在GameDecks.deck_type字段中使用rails枚举。