Rails4测试嵌套资源与多个URL参数 - Rails 4 testing nested resources with multiple URL params

- 此内容更新于:2016-02-01



I have been at this for a few hours, still can't figure it out. I have 2 tests on 2 actions on a nested resources controller. requests is the parent resources route, and response is the nested resources route.

These 2 tests give me a no route matches error. Does not make sense. In the first test, it tries to run the update action instead of the edit. Here are my tests:

test "should get edit" do
  assert_routing edit_request_response_path(@myresponse.request_id, @myresponse), { :controller => "responses", :action => "edit", :request_id => @myresponse.request_id.to_s, :id => @myresponse.id.to_s }
  get :edit, params: { id: @myresponse, request_id: @myresponse.request_id }
  assert_response :success

test "should update response" do
  post :update, :request_id => @myresponse.request_id, response: { body: @myresponse.body, request_id: @myresponse.request_id, status: @myresponse.status, subject: @myresponse.subject, user_id: @myresponse.user_id }
  assert_redirected_to response_path(assigns(:response))

Here are the errors:

3) Error:
ActionController::UrlGenerationError: No route matches {:action=>"edit", :controller=>"responses", :params=>{:id=>"980190962", :request_id=>"999788447"}}
test/controllers/responses_controller_test.rb:43:in `block in <class:ResponsesControllerTest>'

4) Error:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"responses", :request_id=>"999788447", :response=>{:body=>"This is the body", :request_id=>"999788447", :status=>"draft", :subject=>"This is the subject", :user_id=>"175178709"}}
test/controllers/responses_controller_test.rb:48:in `block in <class:ResponsesControllerTest>'

In this case you might want to use shallow nesting since there is no reason to go through request if you can get to a response by /response/:id.

resources :requests, shallow: true do
  resources :response

test "should get edit" do
  assert_routing edit_response_path(@myresponse), { :controller => "responses", :action => "edit", :id => @myresponse.id.to_s }
  get :edit, params: { id: @myresponse, request_id: @myresponse.request_id }
  assert_response :success

However naming your business logic objects Request and Response is a big misstake. These are already key concepts in Rails which correspond to the request from the client and the response sent to the client by rails.

You will end up confusing yourself and any poor sucker that has to work on the project. Plus you will end up masking the request and response methods that are pretty important parts of the ActionController API.

Use some other synonym instead.