Rspec, Порядок загрузки модели, приборы и вызов named_scope - PullRequest
0 голосов
/ 12 ноября 2009

У меня есть несколько игроков, и игроки имеют состояние торговли. Вместо того, чтобы жестко кодировать торговые состояния, такие как «активный» и «неактивный», а затем нужно искать строки, я подумал, что был бы умен и имел бы отдельную модель TradeState, чтобы у игрока был trade_state_id (игрок может быть только в одно состояние торговли за раз).

Теперь было бы удобно иметь возможность получить всех активных игроков, используя именованные области, а затем произнеся «Player.active». Для этого мне нужно получить идентификатор записей TradeState, который соответствует 'active', поэтому я придумал это в классе Player:

named_scope :active, :conditions => {:trade_state_id => TradeState.active.first.id}

Это работает как брелок при тестировании в скрипте / консоли, но не работает, когда я иду на тестирование. Я использую RSpec, но подозреваю, что это не уместно. Когда я запускаю самый простой тест, я получаю следующую ошибку:

"Называется id для nil, который по ошибке будет 4"

Насколько я могу судить, среда тестирования загружает и анализирует модели в алфавитном порядке. Фреймворк анализирует вызов named_scope в модели Player и покорно ищет идентификатор первой активной записи TradeState. Однако эта модель еще не обработана и не готова, поэтому возникает ошибка получения идентификатора nil.

Сначала я подумал, что это потому, что в таблице trade_states может не быть никаких записей, поэтому я создаю и сохраняю trade_states, которые мне нужны, в блоке before (: each), но это не сработало. Тогда я сделал несколько приборов и попытался загрузить их, но это не сработало.

Это кажется правдоподобным? Есть ли другие объяснения? Как насчет обходных путей? Я мог бы попробовать издеваться над объектом TradeState, и я попробую.

Большое спасибо за ваше время.

Ответы [ 3 ]

0 голосов
/ 14 ноября 2009

Это на самом деле потенциально «ожидаемый» результат. Если у вас нет активных игроков, то

TradeState.active

пусто и, следовательно,

TradeState.active.first

ноль,

и, следовательно,

TradeState.active.first.id

вызывает Object::id для нулевого объекта.

Вы можете попробовать:

TradeState.active.empty? ? 0 : TradeState.active.first[:id]

В любом случае, убедитесь, что вы включили trade_states только для того, чтобы убедиться, что они присутствуют для объединения.

0 голосов
/ 15 ноября 2009

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

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

Поэтому я сделал TradeState отдельным классом, который больше не является производным от ActiveRecord, и определил нужные мне константы.

Спасибо всем за ваши мысли и решения.

0 голосов
/ 13 ноября 2009

Этот фрагмент кода, который вы упомянули, исполняется, когда проигрыватель «загружен». Таким образом, даже если вы создадите установочные данные в блоке before (: each), эта модель могла бы быть загружена еще до этого. Чтобы решить проблему, вы можете попробовать что-то вроде:

named_scope :active, lambda { {:conditions => {:trade_state_id => TradeState.active.first.id} } }

Это гарантирует, что TradeState.active вызывается всякий раз, когда вы вызываете named_scope.

Но чего вы достигнете, позвонив по номеру TradeState.active.first. Вместо этого вы можете сделать это таким приятным способом

:conditions => {:trade_state_id => TradeState::ACTIVE}

со следующим кодом на вашей модели TradeState:

class TradeState < ActiveRecord::Base
  def self.const_missing(sym)
    const_set(sym, find_by_name(sym.to_s))
  end
end
...