Ассоциации объектов с использованием datamapper

#ruby #rake #datamapper #padrino

#ruby #грабли #datamapper #падрино

Вопрос:

Я пытаюсь назначить игроков в клуб. В клубе n игроков, и игрок принадлежит к клубу. В клубе может быть не более 23 игроков и не более 2 игроков, играющих на одной позиции.

 clubs = Club.all #Club is a datamapper object. Returns 20 clubs
to_generate = 10000
while (to_generate > 0)
  p = Player.new #Player is a datamapper object
  p.position = position #position is a random integer defined elsewhere

  clubs.each do |club|
    count = 0
    club.players.each do |club_player|
      if (club_player.position == p.position)
        count  = 1
      end
    end
    if (count < 2 amp;amp; club.players.length < 22)
      club.players << p
      p.club = club
    end
  end
  p.save
  to_generate -= 1
  

завершение

В конце сценария я ожидаю, что во всех клубах будет 22 игрока. Почему это не так?

РЕДАКТИРОВАТЬ: в конце сценария я получаю только 22 игрока, назначенных последнему клубу (20), и генерируется 10000 игроков

Комментарии:

1. Сколько игроков у каждого клуба в конце сценария?

2. Я отредактировал вопрос. В конце сценария я получаю только 22 игрока, назначенных последнему клубу (20), и генерируется 10000 игроков

3. Я думаю, у меня есть хороший ответ для вас.

Ответ №1:

Проблема 1. Вы можете превысить максимальное количество игроков в команде и на позиции

Эти строки

 if (count < 3 amp;amp; club.players.length < 23)
  club.players << p
  p.club = club
end
  

можно резюмировать как «Вы можете добавить игрока в клуб, если в клубе менее 23 игроков и на этой позиции уже находится менее 3 игроков».

Это означает, что он позволяет вам добавить еще один… в общей сложности 3 для позиции и 23 для команды. Так что эта часть логики неверна. Вместо этого вы хотите

 if (count < 2 amp;amp; club.players.length < 22)
  

Проблема 2. Случайное число может не гарантировать, что у вас есть правильные типы игроков

Если позиция генерируется случайным образом, вы не можете быть уверены, что у вас будет достаточно игроков нужного типа. Что, если, например, случайное число всегда совпадало с 2? У вас никогда не будет полной команды.

Проблема 3. как только игрок назначен, вы продолжаете пробовать другие клубы

Как только вы назначите игрока, вам не следует больше смотреть на клубы. Для этого вам нужно вырваться из each блока.

 if (count < 3 amp;amp; club.players.length < 23)
  club.players << p
  p.club = club
  break
end
  

Даже если вы вызываете club.players << p несколько раз для одного и того же игрока, DataMapper знает о вашей индивидуальной ассоциации, и последнее задание «выигрывает».

Комментарии:

1. Проблема 1: хорошо! Проблема 2: я генерирую 10000 игроков, нет простого способа, которым это могло бы произойти.

2. Что касается проблемы 2, это правда, что это маловероятно. Но лучше иметь детерминированное поведение. Таким образом, вместо того, чтобы просто использовать 10000 итераций для решения проблемы, вы могли бы сделать свой цикл while обусловленным проверкой того, есть ли в каждой команде требуемые 22 игрока.