cerebris / jsonapi-resources

A resource-focused Rails library for developing JSON:API compliant servers.
http://jsonapi-resources.com
MIT License
2.32k stars 532 forks source link

ActionNotFound: The action 'create' could not be found #635

Closed rlee0001 closed 8 years ago

rlee0001 commented 8 years ago

I'm trying to create a controller test using MiniTest to test my JSONAPI::ResourceController. Most of the actions work fine from within the test (index, show, update, etc...), but when I try to call create, I get an ActionNotFound error. This is happening for all JSONAPI::ResourceControllers, always for the create action. When tested from a web browser with the server actually running, create works perfectly fine. So it has something to do with testing.

My test looks like this:

post :create, data: { ... }

And the error is:

AbstractController::ActionNotFound: The action 'create' could not be found for Api::V1::UsersController

Using pry and poking around a bit, I've determined that the immediate cause is here:

actionpack-4.2.3/lib/abstract_controller/base.rb @ line 257 AbstractController::Base#method_for_action

    256: def method_for_action(action_name)
 => 257:   if action_method?(action_name)
    258:     action_name
    259:   elsif respond_to?(:action_missing, true)
    260:     "_handle_action_missing"
    261:   end
    262: end

For the JSONAPI::ResourceControllers, that action_method? check returns false for the create action. Going deeper, I get this:

actionpack-4.2.3/lib/abstract_controller/base.rb @ line 188 AbstractController::Base#action_method?

    187: def action_method?(name)
 => 188:   self.class.action_methods.include?(name)
    189: end

And inspecting self.class.action_methods gives this:

=> #<Set: {"context",
 "base_response_meta",
 "server_error_callbacks",
 "index",
 "show",
 "show_relationship",
 "create_relationship",
 "update_relationship",
 "update",
 "destroy",
 "destroy_relationship",
 "get_related_resource",
 "get_related_resources",
 "process_request",
 "create_operations_processor"}>

Note the absence of the create action. I just can't figure out why. I don't do anything interesting in the controller...in fact, the controller is blank except my implementation of context and base_response_meta and my inclusion of Pundit. I just extend JSONAPI::ResourceController.

Since this is only an issue when running tests, I'm wondering if there is something JSONAPI::Resources is doing, something Pundit is doing, or something MiniTest is doing.

rlee0001 commented 8 years ago

Figured this out. FactoryGirl was being included in test_helper.rb, and adding itself as an ancestor of Object, defining a create method there. Any method defined by an abstract superclass of your controller is automatically excluded from action_methods. This issue wasn't related to JSONAPI::Resources, and could affect any rails project. I guess, be careful with what you include in test_helper.rb.