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.