views:

268

answers:

1

I am developing a card game server, for a game where each player has a deck and a discard pile. To reflect the fact that a given card could be located in a player's deck or their discard pile, I have my Player model set up as follows:

class Player < ActiveRecord::Base
  belongs_to :game

  has_many :deck_cards, :class_name => "Card",
                        :conditions => "location = 'deck'",
                        :order => "position",
                        :dependent => :delete_all

  has_many :discard_cards, :class_name => "Card",
                           :conditions => "location = 'discard'",
                           :order => "position",
                           :dependent => :delete_all
end

Is it possible to define my Card model in such a way that I can have it acts_as_list with each card in exactly one list (either deck or discard for a single player)?

+1  A: 

Your problem is not validations, its more that acts_as_list will not allow more than list over a single belongs_to relationship.

This following validation will ensure that a card is in either a player's discard or deck list but not both.

validates_uniqueness_of [:fields, :that, :uniquely, :describe, :a, :card],
  :scope => [:player_id, :location]

You should be able to use STI to achieve the multiple lists you desire. Note: this is untested but should at least put you on the right track.

class Card < ActiveRecord::Base
  belongs_to :player
  validates_uniqueness_of [:fields, :that, :uniquely, :describe, :a, :card],
    :scope => [:player_id, :location]
  set_inheritance_column :location
end

class DeckCard < Card
  acts_as_list, :scope => :player
end

class DiscardCard < Card
  acts_as_list, :scope => :player
end

class Player
  belongs_to :game
  has_many :deck_cards, :order => "position",
                        :dependent => :delete_all

  has_many :discard_cards, :order => "position",
                           :dependent => :delete_all
end
EmFi
Not what I'm looking for (I think). I want Card to use acts_as_list at the scope of Player, for either deck or discard.... I think. Hmm. Is that going to make it hard to, say, move cards from top of deck to top of discard?
Chris
The validation ensures that a card is in only one list. However I was not familiar with acts_as_list. The source of the plugin does not suggest that it you can define two lists over the same belongs_to relation. Solution has been updated to reflect this.
EmFi
I like this - so I'm going to Up it - but sadly it doesn't help me. My Cards come in different types so I'm already using STI to distinguish those. If nothing better comes along, I'll also Accept this in a few days.
Chris
You could potentially use a polymorphic join table that uses STI as described above. Belonging to a card type and player as well as having a list type. Unfortunately I haven't the time to craft an example for you. Also don't worry about accepting the answer if it doesn't work for you. I've got more than enough reputation.
EmFi