Search code examples
ruby-on-railsruby-on-rails-5actionviewactioncontrollerjbuilder

how could a new gem in Gemfile (AccessGranted) with no dependencies break ActionView/Jbuilder?


In a rails 5.1 project, I have a controller like Api::V1::ResourcesController with a method like #create; I eventually invoke render status: 201, formats: :json. This has, as I expect, been resulting in a load of a Jbuilder view located at app/views/api/v1/resources/create.json.jbuilder.

I recently added the AccessGranted gem to my project, and after doing so (with no code changes), I find that my invocation of render is still producing the desired 201 status, but is always producing (single space character) as the body. Furthermore, some inspection with pry seems to suggest the file is not being found by the lookup_context, however I can't say why this is as I don't really know how to trace the causal hierarchy here.


Update:

I have found that once I include AccessGranted, the ancestry of my controller class no longer includes ActionView::Rendering. It includes AccessGranted::Rails::ControllerMethods as intended, but has no other changes to ancestry.


The thing that disturbs me here is that AccessGranted is a tiny gem, and I have been able to review it in its entirety in about twenty minutes, without any indication in it as to why it would muck with rails. Is there even something specific I could look for in the new gem to tell what it might be changing just by its inclusion in the gem file?

Ideally I would like to know what exactly has happened here, but even without that I have some difficulty navigating the dynamic ruby system to start getting reliable traces of these files. Some things I have tried in my investigation:

  • inspected the Controller object. I see that it has not experienced a change of formats or _prefixes
  • walked through the flow leading to setting the response. The jbuilder is invoked during render_templates in the good case, but after adding the gem, it is NEVER invoked
  • tried to invoke methods directly on lookup_context while prying, but not reached conclusive results.

Solution

  • It turns out that the gem in question (AccessGranted) invokes a class_eval on ActionController::API at module load time, which is before Jbuilder's rail tie invocation, and thus Jbuilder has not yet executed its patch to ApiController. As such, ActionController::API, which was a parent to my controller class, was loaded as such without ActionView::Rendering.

    This load order is not canonical in Rails as far as I can tell, so I consider this a problem with AccessGranted. As such, I submitted a PR to AccessControl to have it conform to the Rail Tie hook mechanism.