Как определить вызываемый маршрут в спецификации контроллера RSpec

У меня есть спецификация контроллера RSpec, и я пытаюсь понять, как узнать, какой именно маршрут вызывается в моем примере.

В services_controller_spec.rb:

describe 'create comment' do
  let!(:service) { FactoryGirl.create(:service) }

  describe 'with valid comment' do
    it 'creates a new comment' do
      expect {
        post :add_comment, id: service.id
      }.to change(service.service_comments, :count).by(1)

      expect(response).to redirect_to(service_path(service))
    end
  end
end

Есть ли способ pp или puts маршрут, который отправляется по почте?

Я спрашиваю, потому что хочу post на маршрут /services/:id/add_comment и хочу проверить, куда именно идет маршрут.

Мой routes.rb для этого маршрута:

resources :services do
  member do
     post 'add_comment'
  end
end

person sainid    schedule 25.05.2016    source источник
comment
Помогло бы показать блок describe ServicesController.   -  person Dave Schweisguth    schedule 26.05.2016


Ответы (1)


Вы можете напечатать имя маршрута, используемого в спецификации контроллера rspec-rails, примерно так:

routes.formatter.send(
  :match_route,
  nil,
  controller: ServicesController.controller_path,
  action: 'add_comment', # what you passed to the get method, but a string, not a symbol
  id: service.id         # the other options that you passed to the get method
) { |route| puts route.name }

rspec-rails использует маршрут только для внутренних целей. Выше показано, как rspec-rails (на самом деле ActionController::TestCase, который использует rspec-rails) ищет и использует маршрут, но с блоком, который просто печатает маршрут.

Между вызовом post в спецификации и приведенным выше существует множество вызовов методов, поэтому, если вы хотите понять, как rspec-rails попадает в приведенное выше, я предлагаю поставить точку останова в ActionDispatch::Journey::Formatter.match_routes перед запуском вашего примера.

Обратите внимание, что спецификация контроллера rspec-rails не использует маршрут, чтобы решить, какой метод действия вызывать или какой класс контроллера вызывать его; он уже знает их из класса контроллера, который вы передаете в describe, и из действия, которое вы передаете методу действия (get, post и т. д.). Однако он ищет маршрут и использует его для форматирования среды запроса. Помимо прочего, он помещает путь в request.env['PATH_INFO'].

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

person Dave Schweisguth    schedule 25.05.2016
comment
Я попытался запустить код, который вы предоставили выше, но получил сообщение об ошибке «undefined method: formatter». Мысли? Мне нужно импортировать что-нибудь новое? Спасибо за помощь. - person sainid; 25.05.2016
comment
Какие версии Rails и rspec-rails вы используете? - person Dave Schweisguth; 25.05.2016
comment
Рельсы 4.1.8 Rspec 3.4.4 - person sainid; 25.05.2016
comment
Странный. У меня это работает с Rails 4.1.8, и я использую ту же версию RSpec. Что puts routes.class говорит? Или puts routes.methods? Или puts routes.private_methods? - person Dave Schweisguth; 25.05.2016
comment
Я выполнил эти команды и искал formatter метод, но не смог его найти. Тем не менее, я нашел format метод, но это private_method ‹br/› puts routes.class дает Array - person sainid; 26.05.2016
comment
Мой routes.class - это ActionDispatch::Routing::RouteSet, возвращенный метод спецификации контроллера rspec-rails. Что мы могли бы делать по-другому? Rails.application.routes работает? - person Dave Schweisguth; 26.05.2016
comment
Что странно, когда я слежу за замедлением routes, это также приводит меня к тому же controller_example_group.rb. Когда я puts Rails.application.routes.class, я получаю ActionDispatch::Routing::RouteSet, я использовал явное замедление, и это сработало. Я вижу маршрут, по которому он звонит. Спасибо за помощь! - person sainid; 26.05.2016