Лучший способ протестировать именованные области видимости в Rails4

В рамках миграции с Rails 3.2 на Rails 4 все именованные области видимости нуждаются в блоке proc. Подробнее читайте здесь: http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#active-record

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

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

# models/offer.rb
class Offer < ActiveRecord::Base

  scope :roster, where(:on_roster => true)
  scope :commit, where("status_id > 5")

end

Если я использую каждую опцию области видимости для независимых вызовов в консоли rails, запросы строятся правильно, и результаты возвращаются, как и следовало ожидать в Rails 3.2:

$ rails c
2.0.0-p247 :001 > Offer.roster.all.size
  Offer Load (1.6ms)  SELECT "offers".* FROM "offers" WHERE "offers"."on_roster" = 't'
=> 1
2.0.0-p247 :002 > Offer.commit.all.size
  Offer Load (1.6ms)  SELECT "offers".* FROM "offers" WHERE (status_id > 5)
=> 3

Однако, если я объединю два вызова области видимости вместе в консоли rails, в каждый запрос будут включены только ограничения из последней области в цепочке:

2.0.0-p247 :003 > Offer.roster.commit.all.size
  Offer Load (1.4ms)  SELECT "offers".* FROM "offers" WHERE (status_id > 5)
 => 3
2.0.0-p247 :004 > Offer.commit.roster.all.size
  Offer Load (0.7ms)  SELECT "offers".* FROM "offers" WHERE "offers"."on_roster" = 't'
 => 1 

Теперь, если я отредактирую свою модель, чтобы добавить процесс во вторую названную область, например:

class Offer < ActiveRecord::Base

  scope :roster, where(:on_roster => true)
  scope :commit, -> { where("status_id > 5") }

end

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

$ rails c
2.0.0-p247 :003 > Offer.roster.commit.all.size
  Offer Load (1.4ms)  SELECT "offers".* FROM "offers" WHERE "offers"."on_roster" = 't' AND (status_id > 5)
 => 0 
2.0.0-p247 :004 > Offer.commit.roster.all.size
  Offer Load (0.7ms)  SELECT "offers".* FROM "offers" WHERE "offers"."on_roster" = 't'
 => 1 

Итак, первый результат правильный и загружает обе области, а второй неверен и загружает только последнюю область. Затем, если вы измените обе области для использования процедур, например:

# models/offer.rb
class Offer < ActiveRecord::Base

  scope :roster, -> { where(:on_roster => true) }
  scope :commit, -> { where("status_id > 5") }

end

Наконец-то вы получите ожидаемое поведение:

$ rails c
2.0.0-p247 :002 > Offer.roster.commit.all.size
  Offer Load (1.3ms)  SELECT "offers".* FROM "offers" WHERE "offers"."on_roster" = 't' AND (status_id > 5)
 => 0
2.0.0-p247 :001 > Offer.commit.roster.all.size
  Offer Load (1.7ms)  SELECT "offers".* FROM "offers" WHERE "offers"."on_roster" = 't' AND (status_id > 5)
 => 0 

Одно замечание по этому поводу: вызов reload! в консоли rails не приведет к обновлению поведения осциллографов после того, как вы обновили и сохранили свою модель. Вы должны завершить сеанс консоли rails и начать новый, чтобы правильно выбрать proc и non-proc.

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

Есть ли простой способ проверить с помощью Rspec с Rails4, находится ли указанная область в блоке процедуры или лямбда?


person Paul Pettengill    schedule 20.09.2013    source источник
comment
Ответ прост - ВСЕГДА используйте объект proc в ваших областях видимости.   -  person Almaron    schedule 20.09.2013
comment
^ Ваш ответ полностью упускает суть. Вопрос в том, как с помощью тестирования убедиться, что все ваши прицелы имеют процедуры. Я ищу решение, которое позволит настроить правильный TDD для перехода от красного к зеленому.   -  person Paul Pettengill    schedule 20.09.2013
comment
Тогда вы должны были вставить свои тесты, которые проходят, когда они не должны, вместо того, чтобы перечислять всю историю, которая является второстепенным секретом.   -  person Almaron    schedule 20.09.2013
comment
^ Возможно, вставленные результаты тестов могли быть полезны для кого-то, но я предполагаю, что большинство людей придут к тому же выводу, что и я. Утверждения и ответы консоли rails более ясно и лаконично продемонстрировали основную проблему того, как были построены запросы, которые привели к ложным срабатываниям, чем показ самих ложных срабатываний, которые были бы лишены какой-либо информации о том, почему эти тесты возвращались с ложными срабатываниями, и почему другие потенциальные тесты также могут быть ошибочными.   -  person Paul Pettengill    schedule 20.09.2013


Ответы (1)


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

Единственное решение, о котором я мог думать, - это использование RR и проксирование метода области. Таким образом вы можете вызвать исключение, если тело не отвечает на вызов. В ваших тестах вы ожидаете, что не возникнет никаких исключений. Но я сомневаюсь, что это сработает, потому что как только вы настроили прокси, класс уже был загружен и, следовательно, был вызван метод области.

Я предполагаю, что вместо принудительного использования Proc с помощью теста лучше переписать метод scope, чтобы вообще не разрешать не-procs / -lambdas.

Для справки: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/scoping/named.rb

person lawitschka    schedule 20.09.2013
comment
Я согласен с тем, что требование обезьяны, исправляющее определение именованной области, гарантирует, что для всех именованных областей определены procs / lambda. Я надеялся найти простой способ протестировать его, так как для людей, переходящих на 4.0, еще рано, я подумал, что такой тест будет полезен для других, которые хотят убедиться, что их обновление правильное. - person Paul Pettengill; 22.09.2013