ActiveRecord и получение неиспользуемых записей из отношения, find_by_sql или named_scope?

Некоторый контекст:

У меня есть несколько моделей, которые выглядят так

Актёр has_many Действия

Действие принадлежит актеру, принадлежит решение

Решение имеет_много действий, принадлежит подсказке

Подсказка has_many решений

Что мне нужно сделать, так это в ActorsController получить случайную подсказку, которая еще не использовалась из всех доступных подсказок.

В моем приложении rails Актеры получают подсказки, которые дают им несколько вариантов выбора. Когда они делают выбор (решение), это сохраняется в базе данных как действие.

Я пробовал различные итерации named_scope и find_by_sql, но ни один из них не работал, и я даже не уверен, правильно ли я начал с них, поскольку в работе так много моделей, и я, кажется, не знаю когда начать.

Я надеюсь, что это дает представление о том, с чем я столкнулся. Я был бы признателен даже за общее указание составить план атаки.

Спасибо!

изменить

После нескольких часов раздумий я понял, что что-то работает, но очень беспорядочно, а мои журналы заполнены вызовами SQL, так что это определенно может выдержать критический взгляд.

В модели подсказки:

  named_scope :available, lambda { |used| 
    { :conditions => ["id NOT IN (?)", used ] }
  }

В модели актера:

  def used_prompts
    prompts = Array.new
    if self.acts && self.acts.length >= 1
      self.acts self.acts.each { |act| prompts.insert(0, act.decision.prompt.id) }
      return prompts.sort
    else
      return [0]
    end
  end

И в ActorsController:

@prompt = Prompt.available(@actor.used_prompts).find(:first, :order => "RAND()")

Очевидно, что блок if в used_prompts является одной из виновных сторон, но я не знаю лучшего способа справиться с этим, так как я не могу сделать self.acts.decisions.each или что-то в этом роде. Может кто меня научит :)


comment
использование RAND() действительно сильно замедлит ваши запросы, к вашему сведению.   -  person Preston Marshall    schedule 28.01.2011


Ответы (1)


Проще всего было бы добавить after_create или аналогичный обратный вызов в модель решения, который помечает связанное приглашение как использованное. Вы также можете добиться этого, используя некоторые соединения, но это потребует немного больше работы и, возможно, приведет к проблемам с масштабируемостью (если вас это волнует).

person Preston Marshall    schedule 27.01.2011
comment
Спасибо за ответ Престон. К сожалению, подсказки будут повторно использоваться каждым отдельным актером, поэтому установка для них флага вызовет другие проблемы. У вас может быть точка зрения о масштабируемости, но я боюсь, что, возможно, уже пересек эту точку :) - person John; 27.01.2011
comment
Позвольте мне попытаться понять. Ваша цель состоит в том, чтобы предложить актеру только невыбранные (этим актером) подсказки? - person Preston Marshall; 28.01.2011
comment
Правильный. Подсказки перерабатываются для использования другими Актерами, но каждому отдельному Актеру нужно давать какую-либо Подсказку только один раз. Подсказки представлены во время текстовой игры, поэтому подача повторных подсказок делает игровой процесс несколько хромым. Кто хочет, чтобы ему задавали один и тот же вопрос 3-5 раз из 15, верно? Дети, на которых мы тестировали приложение, сделали это совершенно ясно, благослови их отсутствие тонкости :) - person John; 28.01.2011