简体   繁体   中英

helper_method not working with ActionCable

I am new to Ruby on Rails and I have been trying to understand ActionCable for the past 2 months.

I have a helper method :current_user defined in

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  helper_method :current_user

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

end

When calling it from

app/views/layouts/application.html.erb

<%= current_user.id %>

it displays: 1 for example. However, when I bring :current_user to Action Cable, it displays empty or nil .

app/channels/application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user
      logger.add_tags "ActionCable", "User: #{current_user.id}"
    end

  end
end

Terminal: Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket) There was an exception - NoMethodError(undefined method `id' for nil:NilClass)

Thanks in advance for any help or direction.

If you see the doc you provided, you will know that identified_by is not a method for a Channel instance. It is a method for Actioncable::Connection. From Rails guide for Actioncable Overview, this is how a Connection class looks like:

#app/channels/application_cable/connection.rb

module 
 ApplicationCable class Connection < ActionCable::Connection::Base
 identified_by :current_user

  def connect 
      self.current_user = find_verified_user 
  end 

  private
  def find_verified_user 
   if current_user = User.find_by(id: cookies.signed[:user_id])
       current_user 
   else
       reject_unauthorized_connection 
   end 
  end
 end 
end

As you can see, current_user is not available here. Instead, you have to create a current_user here in connection. The websocket server doesn't have a session, but it can read the same cookies as the main app. So I guess, you need to save cookie after authentication. Thanks ASAP..

There is no relation between your ApplicationController (or controllers in general), helpers and ActionCable. They are completely separate concepts.

Controllers respond to regular HTTP requests. They inherit from ActionController::Base , ActionController::Api or ActionController::Metal .

Helpers are just modules located in your app/helpers directory which are included in the view context. Which is the context that controllers provide the view. When you call helper_method :current_user you make that method available in the controller as well.

But an ActionCable Connenction is not a controller. Nor does it have anything really to do with a controller or MVC.

Connections form the foundation of the client-server relationship. For every WebSocket accepted by the server, a connection object is instantiated.

Websockets is a completely seperate protocol from HTTP.

While you could include your helpers in a Connection class since they are just modules its not going to help you here as thesession middleware is not available in ActionCable . So there ain't no way that little session based auth you built off some tutorial is magically going to start working in ActionCable.

You can still access the cookies though through cookies.signed so what you need to do is modify your auth system so that it sets a signed HTTP cookie as well which you then read in ActionCable.

Helper methods only available in your views. Remember that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM