Однозначная ассоциация DataMapper

Я новичок в DataMapper и пытаюсь создавать модели для следующего сценария:

У меня есть несколько пользователей (с именем пользователя, паролем и т. Д.), Которые также могут быть игроками, судьями или обоими (так что наследование одной таблицы не вариант). Базовые модели будут:

class User
  include DataMapper::Resource
  property :id, Serial
  # Other user properties go here  
end

class Player
  include DataMapper::Resource
  property :id, Serial
  # Other player properties go here
  # Some kind of association goes here
end

class Referee
  include DataMapper::Resource
  property :id, Serial
  # Other referee properties go here
  # Some kind of association goes here
end

DataMapper.finalize

Однако я не уверен, какие ассоциации добавить к игроку и судье. С belongs_to :user несколько игроков могут быть связаны с одним и тем же пользователем, что не имеет смысла в моем контексте. В терминах РСУБД я предполагаю, что мне нужно уникальное ограничение на внешний ключ в таблицах Players и Referees.

Как мне сделать это в моей модели DataMapper? Должен ли я сам выполнять проверку во время валидации?


person mwittrock    schedule 11.06.2013    source источник


Ответы (2)


Есть разные способы сделать это. Вот один вариант:

class User
  include DataMapper::Resource
  property :id, Serial
  # Other properties...
  has 1, :referee, :required => false
  has 1, :player, :required => false
end

class Referee
  include DataMapper::Resource
  # DON'T include "property :id, Serial" here
  # Other properties...
  belongs_to :user, :key => true
end
class Player
  include DataMapper::Resource
  # DON'T include "property :id, Serial" here
  # Other properties...
  belongs_to :user, :key => true
end

Действуйте в соответствии с моделями судьи / игрока, например:

u = User.create(...)
u.referee = Referee.create(...)
u.player = Player.create(...)

u.player.kick_ball() # or whatever you want to call
u.player.homeruns
u.referee.flag_play() # or whatever.

Посмотрите, работает ли это. На самом деле я его не тестировал, но все должно быть хорошо.

person AlexQueue    schedule 13.06.2013
comment
Спасибо за Ваш ответ. Однако эти модели по-прежнему позволяют мне создавать несколько игроков, связанных с одним и тем же пользователем. - person mwittrock; 13.06.2013
comment
@mwittrock Понятно. Отредактировано, чтобы предотвратить это. Теперь подклассы используют внешний ключ пользователя в качестве своих первичных ключей. - person AlexQueue; 13.06.2013
comment
Кажется, это правильная взаимно-однозначная ассоциация в DataMapper. Наслаждайтесь репутацией :-) - person mwittrock; 14.06.2013
comment
О, награду можно назначить за 6 часов. - person mwittrock; 14.06.2013

Предыдущий ответ работает, кроме :required => false, не распознается для свойств has 1.

Это также сбивает с толку, потому что для has n свойств вы можете использовать new прямо в свойстве или иным образом рассматривать его как коллекцию. В вашем примере у вас может возникнуть соблазн написать код

u = User.create ...
u.referee.create ...

Но это не удается в случае has 1, потому что свойство представляет собой одно значение, которое начинает свою жизнь как nil, и поэтому вы должны использовать метод, указанный в предыдущем ответе. Кроме того, необходимость явного включения ассоциации belongs_to в ключ немного сбивает с толку.

Кажется, что он выполняет проверки и имеет правильные действия ассоциации (поэтому u.save также сохранит упомянутый Referee). Я просто хотел бы, чтобы между has n и has 1 было больше согласованности.

person cvkline    schedule 17.03.2014