Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError when rendering a partial directly #41

Open
Quintasan opened this issue Sep 27, 2021 · 2 comments
Open

TypeError when rendering a partial directly #41

Quintasan opened this issue Sep 27, 2021 · 2 comments

Comments

@Quintasan
Copy link

Quintasan commented Sep 27, 2021

class TeasController < ApplicationController
  def create
    result = NewTeaService.new.call(params.to_unsafe_h)

    case result
    in Success[:created, Tea => tea]
      render tea, status: :created
    in Failure[_, errors]
      render json: errors, status: :unprocessable_entity
    end
  end
end

This action tries to render app/views/teas/_tea.json.jbuilder

# app/views/teas/_tea.json.jbuilder
tea.slice(*%i[
  id
  name
  country
  created_at
  updated_at
])

but fails with

TypeError (no implicit conversion of Array into String):

rack (2.2.3) lib/rack/etag.rb:69:in `<<'
rack (2.2.3) lib/rack/etag.rb:69:in `block in digest_body'
actionpack (6.1.4.1) lib/action_dispatch/http/response.rb:158:in `each'
actionpack (6.1.4.1) lib/action_dispatch/http/response.rb:158:in `each_chunk'
actionpack (6.1.4.1) lib/action_dispatch/http/response.rb:140:in `each'
actionpack (6.1.4.1) lib/action_dispatch/http/response.rb:76:in `each'
actionpack (6.1.4.1) lib/action_dispatch/http/response.rb:493:in `each'
rack (2.2.3) lib/rack/etag.rb:67:in `digest_body'
rack (2.2.3) lib/rack/etag.rb:31:in `call'
rack (2.2.3) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.3) lib/rack/head.rb:12:in `call'
activerecord (6.1.4.1) lib/active_record/migration.rb:601:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (6.1.4.1) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (6.1.4.1) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/debug_exceptions.rb:29:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (6.1.4.1) lib/rails/rack/logger.rb:37:in `call_app'
railties (6.1.4.1) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (6.1.4.1) lib/active_support/tagged_logging.rb:99:in `block in tagged'
activesupport (6.1.4.1) lib/active_support/tagged_logging.rb:37:in `tagged'
activesupport (6.1.4.1) lib/active_support/tagged_logging.rb:99:in `tagged'
railties (6.1.4.1) lib/rails/rack/logger.rb:26:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/request_id.rb:26:in `call'
rack (2.2.3) lib/rack/runtime.rb:22:in `call'
activesupport (6.1.4.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/static.rb:24:in `call'
rack (2.2.3) lib/rack/sendfile.rb:110:in `call'
actionpack (6.1.4.1) lib/action_dispatch/middleware/host_authorization.rb:98:in `call'
railties (6.1.4.1) lib/rails/engine.rb:539:in `call'
puma (5.5.0) lib/puma/configuration.rb:249:in `call'
puma (5.5.0) lib/puma/request.rb:77:in `block in handle_request'
puma (5.5.0) lib/puma/thread_pool.rb:340:in `with_force_shutdown'
puma (5.5.0) lib/puma/request.rb:76:in `handle_request'
puma (5.5.0) lib/puma/server.rb:447:in `process_client'
puma (5.5.0) lib/puma/thread_pool.rb:147:in `block in spawn_thread'

unless I append .to_json to the partial. Is this working as intended?

@fernandoiwamoto
Copy link

fernandoiwamoto commented Dec 21, 2021

I'm getting same error when I use this:

         ApplicationController.renderer.render(
            partial: 'shared/item',
            locals: { item: item }
          )

and my file is /view/shared/_item.json.jb

@MC-Squared
Copy link

MC-Squared commented Jan 18, 2023

Only tested this for the simple ApplicationController.render(partial: ... case on Rails 7.0.4, but in case anyone else finds themselves here this patch seems to get it working:

module Jb
  module PartialRenderer
    module JSONizer
      def render_partial_template(*)
        rendered_template = super
        rendered_template.instance_variable_set :@body, rendered_template.body.to_json if rendered_template.template.respond_to?(:handler) && (rendered_template.template.handler == Jb::Handler)
        rendered_template
      end
    end
  end
end
::ActionView::PartialRenderer.prepend ::Jb::PartialRenderer::JSONizer

The underlying issue is that jb patches ActionView::TemplateRenderer, but when you call ApplicationController.render(partial: ...) it uses ActionView::PartialRenderer.

Note however that with this patch, calls to render(partial: ... within another view/partial will now also return JSON, which could mess things up with nested partials. Not sure of a good workaround yet other than using JSON.parse inside the views.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants