Devise: How use Aplication.renderer.render from rails 5 with devise

Created on 24 Aug 2016  ·  21Comments  ·  Source: heartcombo/devise

I want to make my app in real time

This is my error

ActionView::Template::Error (Devise could not find the Warden::Proxy instance on your request environment. Make sure that your application is loading Devise and Warden as expected and that the Warden::Manager middleware is present in your middleware stack. If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the Devise::Test::ControllerHelpers module to inject the request.env['warden'] object for you.)
1: -if user_signed_in?
2: .ui.popup.computer{id:"post#{post.id}user#{post.user.id}", style:"padding:0px"}
3: .ui.card
4: .image

I don't know what to do

Help me please.

Most helpful comment

These articles might be helpful:

https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions
http://www.thegreatcodeadventure.com/using-action-controller-renderers-in-rails-5-with-devise/

Citing the first one: "Hopefully, all gems could provide environment fallbacks, and developers would not spend time fixing helper failures by deducing what’s missing from the environment."

All 21 comments

These articles might be helpful:

https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions
http://www.thegreatcodeadventure.com/using-action-controller-renderers-in-rails-5-with-devise/

Citing the first one: "Hopefully, all gems could provide environment fallbacks, and developers would not spend time fixing helper failures by deducing what’s missing from the environment."

Any update on this being resolved without using a hacky work around? Using ApplicationRenderer inside a worker would require passing the request around which seems kind of wrong...

This problem is happening again on Devise 4.3.0 and Rails 5.1.3. I had to follow this blog post:
https://www.stefanwienert.de/blog/2016/04/05/using-rails-5-new-renderer-with-authentication-gems-like-clearance-or-devise/

Note: In my case I needed to render on a sidekiq worker.

hello guys,
any update?

i'm doing a live chat. When i use application controller renderer to render new comments i have the same error message.

[ActiveJob] [CommentBroadcastJob] [29558acd-658a-4a3a-b870-f447881740b8] Error performing CommentBroadcastJob (Job ID: 29558acd-658a-4a3a-b870-f447881740b8) from Async(default) in 34.14ms: ActionView::Template::Error (Devise could not find the Warden::Proxy instance on your request environment.
Make sure that your application is loading Devise and Warden as expected and that the Warden::Manager middleware is present in your middleware stack.
If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the Devise::Test::ControllerHelpers module to inject the request.env['warden'] object for you.):

I cannot find any solution for it.
any updates?

There is no solution. You need to pass in the current user into your
worker. This is the result of you trying to call current user in something
rendered by application renderer.

@jclusso can you be more specific about how I can solve my issue?
if more info is needed, I can post here
thank you

I assume you’re trying to render a view with application renderer that calls something like current_user. You can’t reference anything like that in a view being rendered by application renderer in a worker because it has no idea about warden. You’d have to pass that referenced user through the worker from where you start it. Then pass it into the view at that point. Hope that’s more informative.

If not share the code and maybe I can help.

thank you.
which part of my code is needed?

Where ever is throwing the error. The worker and views associated.

sorry for my late response
Is it better to send you github link?
https://github.com/KickButtowski80/blogwithpolymorphiccoments
if you do mind to take a look at it
I appreciate it

After taking a quick look I see in the CommentBroadcastJob you try and render comments/comment which has a reference to current_admin. You can not reference current_admin in a view rendered by ApplicationRenderer since ApplicationRenderer has no knowledge of stuff in Warden. You must pass the user into the worker and pass it back into the view.

thank you for your response
I am not sure about what you said?
"You must pass the user into the worker and pass it back into the view."
Would you please gimme an example?
Where is this worker?
If you do not mind to elaborate "ou can not reference current_admin in a view rendered by ApplicationRenderer since ApplicationRenderer has no knowledge of stuff in Warden." further I appreciate it .
thank you for your time

Same problem here with @KickButtowski80

Your job “aka” worker.

I’m not sure how else to explain this. I’m on my phone at the moment so I can’t write a full example. Start the job and pass the current_admin as a parameter into the job. You CANNOT call current_admin in a view rendered with ApplicationRenderer. You must render the view and pass it in like

‘’’
render(view_name, current_admin: user)
‘’’

It can be happening when you try to get Devise current_user in some part of code being managed by action cable. like a background job to render comment or something else. you can resolve it by using something like following in your controller, since you cant access warden at a model or job level(according to my limited knowledge): (I call a job right after creation of my comment in CommentsController create action, which calls a private method to render a comment partial containing edit and delete button, for which current_user was required)

 def create
@product = Product.find(comment_params[:product_id])
@comment = @product.comments.build(comment_params)
@comment.save!

gon.comment_id = @comment.id
gon.comment_user_id = @comment.user_id

ActionCable.server.broadcast "chat", comment: render_comment

render :create, layout: false
end


def render_comment
  CommentsController.renderer.instance_variable_set(:@env, {"HTTP_HOST"=>"localhost:3000", 
    "HTTPS"=>"off", 
    "REQUEST_METHOD"=>"GET", 
    "SCRIPT_NAME"=>"",   
    "warden" => warden})

  CommentsController.render(
    partial: 'comments/comment_detail',
    locals: {
      product: @product,
      comment: @comment
    }
  )
end

this will help you resolve warden issue, if you have used devise's current_user in that partial, it will give you the commentor user (as it should since that user initiated the rendering of partial). Now to solve this, if you have a front end framework you might need to fetch the current user from cookies in order to restrict some actions like edit/delete. but if you are working in pure rails the solution I came across is that you have to make a hidden field in the dom having current users id, and you will fetch that id for comparison in a script. you might need to access rails variables in javascript, for that you can use GON gem. I know this answer might contain much more than asked but I've searched alot and no where I found a satisfactory solution to this problem, feel free to discuss.

Update version of https://github.com/heartcombo/devise/issues/4271#issuecomment-328371276 (from https://www.stefanwienert.de/blog/2016/04/05/using-rails-5-new-renderer-with-authentication-gems-like-clearance-or-devise/#devise) :

class ApplicationController < ActionController::Base
  def self.render_with_signed_in_user(user, *args)
    ActionController::Renderer::RACK_KEY_TRANSLATION['warden'] ||= 'warden'
    proxy = Warden::Proxy.new({}, Warden::Manager.new({})).tap{|i| i.set_user(user, scope: :user, run_callbacks: false) }
    renderer = self.renderer.new('warden' => proxy)
    renderer.render(*args)
  end
end

I fixed it like this.
rendered_string = ApplicationController.render( template: 'path_to_view_file', layout: false, assigns: {dummy: Dummy.first} )

I fixed it like this.
rendered_string = ApplicationController.render( template: 'path_to_view_file', layout: false, assigns: {dummy: Dummy.first} )

lol. This is not a fix, this is how it works :

I fixed it like this.
rendered_string = ApplicationController.render( template: 'path_to_view_file', layout: false, assigns: {dummy: Dummy.first} )

lol. This is not a fix, this is how it works :

Yeah, but if you use layout: false, devise will not interfere with the rendering process.

Weird...

Was this page helpful?
0 / 5 - 0 ratings