简体   繁体   English

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

[英]How should I define multiple relationships between the same two models in Rails 5

I have two models: 我有两个模型:

A Game that keeps track of the game state in a card game. 一个Game一个跟踪游戏状态的一个纸牌游戏。

A Deck that manages how cards are stored, shuffled, dealt, etc. 一个Deck管理卡的存储方式,洗牌,处理,等等。

The Game has many different Decks that it has to keep track of at once. Game有许多不同的Decks ,必须立即跟踪。 For example, two separate different draw decks and a discard deck. 例如,两个单独的不同的绘图平台和一个废弃平台。

I'm a little stumped on how I should define these relationships. 我对如何定义这些关系感到有些困惑。 Ideally, I would have Game.draw_type_a Game.draw_type_b and Game.discard that I could work with, and they would each point to a single Deck . 理想情况下,我可以使用Game.draw_type_a Game.draw_type_b和Game.discard,并且它们每个都指向一个Deck I've experimented with has_one :through relationships and traditional one-to-one relationships with defined foreign_keys and classes, but I haven't been able to get this working. 我已经尝试过has_one :through关系以及已定义的foreign_keys和class的传统一对一关系,但是我无法使它正常工作。

I'd really like to keep all the decks as a single model, since there is so much overlap in how they behave. 我真的很想将所有卡座保持为单个模型,因为它们的行为有很多重叠之处。 How should I define the relationships between the three types of deck in the Game and the Deck model. 我应该如何定义的三种甲板之间的关系, GameDeck模型。 What should the migrations look like to implement them? 实施迁移应采用什么样的方式?

I've done something similar in my Adj game . 我在Adj游戏中做了类似的事情。 This is what I would do: 这就是我要做的:

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

I would use a three table solution, namely: games, decks, game_decks(?). 我将使用三表解决方案,即:游戏,套牌,game_decks(?)。

Games has many game_decks. 游戏中有很多game_decks。 GameDecks have a game_id, deck_id, and deck_type (draw_type_a, draw_type_b, etc.), so it belongs to games and belongs to decks Decks has many GameDecks. GameDecks具有game_id,deck_id和deck_type(draw_type_a,draw_type_b等),因此它属于游戏,并且属于Deck。Decks具有许多GameDecks。

Additionally, Games has many Decks through GameDecks, and Decks has many Games through GameDecks. 此外,Games通过GameDecks具有许多Decks,而Decks通过GameDecks具有许多Game。

This allows you to do things like game.decks to retreive all game decks and game.decks.where(deck_type: :draw_type_a) for all of the game's draw_type_a decks (this can be further refined with scopes). 这样,您就可game.decks游戏的所有game.decks.where(deck_type: :draw_type_a)牌组执行game.decks.where(deck_type: :draw_type_a)类的game.decks来恢复所有游戏牌组和game.decks.where(deck_type: :draw_type_a) (可以使用范围进一步完善)。

As a side note, I would use a rails enum for the GameDecks.deck_type field. 附带说明一下,我将在GameDecks.deck_type字段中使用rails枚举。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM