-
Notifications
You must be signed in to change notification settings - Fork 523
Addition of Draper Gem causes empty string output in ActionController::API requests #860
Description
When we add gem 'draper' to our Gemfile in our Rails 5.0.x project, it breaks our ActionController::API requests by causing an empty string to be returned. I believe this is due to our use of the responders gem as well.
We see the debugger hit the following:
# .rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/responders-2.4.0/lib/action_controller/responder.rb
184: def to_format
185: if !get? && has_errors? && !response_overridden?
186: display_errors
187: elsif has_view_rendering? || response_overridden?
=> 188: default_render
189: else
190: api_behavior
191: end
# .rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/responders-2.4.0/lib/action_controller/responder.rb
278: def has_view_rendering?
=> 279: controller.class.include? ActionView::Rendering
280: end
So, has_view_rendering? returns true due to the injection of ActionView::Rendering into the class hierarchy by Draper in the Draper::Compatability::ApiOnly module. This causes the default_render to be called and not the api_behavior which is what we need and see when we don't have the Draper gem in the Gemfile.
The ApiOnly module is run automatically upon gem load to "temporarily" add view_context support to ActionController::API. In the comments it explicitly calls this a "hack" and "temporary solution". If so, there should be a way for developers to opt out of this functionality.
draper/lib/draper/compatibility/api_only.rb
Lines 1 to 23 in aaa06bd
| module Draper | |
| module Compatibility | |
| # Draper expects your `ApplicationController` to include `ActionView::Rendering`. The | |
| # `ApplicationController` generated by Rails 5 API-only applications (created with | |
| # `rails new --api`) don't by default. However, including `ActionView::Rendering` in | |
| # `ApplicatonController` breaks `render :json` due to `render_to_body` being overridden. | |
| # | |
| # This compatibility patch fixes the issue by restoring the original `render_to_body` | |
| # method after including `ActionView::Rendering`. Ultimately, including `ActionView::Rendering` | |
| # in an ActionController::API may not be supported functionality by Rails (see Rails issue | |
| # for more detail: https://github.com/rails/rails/issues/27211). This hack is meant to be a | |
| # temporary solution until we can find a way to not rely on the controller layer. | |
| module ApiOnly | |
| extend ActiveSupport::Concern | |
| included do | |
| alias_method :previous_render_to_body, :render_to_body | |
| include ActionView::Rendering | |
| alias_method :render_to_body, :previous_render_to_body | |
| end | |
| end | |
| end | |
| end |
It seems like a very bad practice to modify class hierarchies just by adding a gem. Is it possible to add a setting to opt out of this behavior - or better, make it opt-in.
PS. Other than this, love the gem.