2013-09-20 3 views
0

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

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

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

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

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

end 

Если я использую каждый опционных на независимых вызовов в рельсах консоли, запросы будут построены правильно, и результаты возвращаются, как можно было бы ожидать в 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 

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

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 

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

$ 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 и начать новый, чтобы заставить proc и non-proc правильно подобрать.

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

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

+0

Ответ прост - ВСЕГДА использовать объект ргос в ваших областях. – Almaron

+0

^Ваш ответ полностью пропустит точку. Вопрос в том, как вы обеспечиваете посредством тестирования, что все ваши области имеют procs. Я ищу решение, которое позволит настроить правильный TDD, чтобы перейти от красного к зеленому. –

+0

Затем вы должны были встать в свои тесты, которые проходят, когда они не должны, а не перечислять целую историю, которая является второстепенным секретом. – Almaron

ответ

0

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

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

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

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

+0

Я согласен с тем, что для этого требуется исправление обезьяны с именем именованного определения области, чтобы все названные области были определены procs/lambda. То, что я надеялся найти, было простым способом протестировать его, поскольку его еще рано, когда люди переходят на 4.0, я полагал, что такой тест будет полезен другим, которые хотят убедиться, что их обновление правильное. –

Смежные вопросы