Ask A Question

Notifications

You’re not receiving notifications from this thread.

Group Chat with ActionCable: Part 5 Discussion

Hi Chris,
How many users is a chatroom-site like this able to handle?

thanks,

Reply

That will depend on how big your server is and it's configuration. I haven't tested any websocket stuff at scale, but I've seen some performance tests for 10,000 users before. It starts to slow down at a point, and they were using simulated things, so never real world data. Your mileage will probably vary quite heavily if you start going past a couple thousand users.

Reply

Hi Chris,

Do you mean 10,000 simultaneous users of the chat, or just having 10,000 users on the site itself?

-Monroe

Reply

10k ActionCable connections.

Reply

Hey Chris,
With this code (no controller action and message creation happens in channel), what is the best way to authenticate the user for message creation? The only solution that comes into my mind is front-end authentication with currentUserId on the body tag and checking with jQuery if there is any number, I don't really like it. Is there a better approach at the moment?

Reply

What we setup earlier was Devise so that you can login and since WebSockets share the same cookies a web request does, when you connect to the WS, it will log you in with Warden (devise's underlying authentication layer) and let you use the WebSocket. Then we have access to the current_user method inside ActionCable just like we do in a normal web request.

On the frontend, you can add a current-user meta tag keep track of it in your JS so that you can customize your frontend to handle things differently if you're not logged in, etc. Check out this episode for more on that: https://gorails.com/episode...

Reply
Marko Manojlovic Marko Manojlovic

Hi Chris,
Awesome tutorials!!!

I followed instructions to refactor the existing code from last episode, but it doesn't work on my end. When I type in the message and press Enter, it doesn't get sent, nothing happens. I tried to log the message, but also nothing... I am not sure what happened there... Did you have similar problems?

Thank you!
Marko

Reply

Hi Chris. You're a life saver with these tutorials!

How would you extend this app to be or allow one-to-one chat. I've been thinking of a channel being created for each user-user combination - and only show it to those users. Conceptually it doesn't sound as an elegant solution to me. How would you go about it? or if you could point me in the right direction.

Thank you,
Alex

Reply

The main thing is probably that you could create a "direct_message" attribute for Channel where you can mark it as a direct message and auto-attach the users (yourself and the person you want to DM). On create, you can attach the users to it, and then pretty much everything else probably works about the same. The navbar probably renders direct message ones separate from the main channels and should only display for users who are in it.

Reply

Hi Chris, thanks for these very good explanations. You mentioned the possibility of disconnecting a user from a channel when he wants to leave.
I don't know if it is explained in one of the two next pro episodes and if not I have two questions :)
I've used your tutorial to build a simple realtime messaging app with Mailboxer. It works pretty well thanks to you. What would be the simplest way to disconnect a user from a channel ? I would call the stop_all_stream function but I don't know exactly how to.
Furthermore, by calling this function, do we disconnect a user from a single chatroom or from all the chatrooms ?
Thanks a lot !

Reply

Interestingly, there isn't a stop_stream method in ActionCable, so you'd have to stop all streams at least right now. Someone has opened a PR with this but it's still pending: https://github.com/rails/ra...

For now, I guess you can either stop_all_streams and reconnect to the ones you want, or you can monkey patch in the code from that pull request. I would probably do that because it's likely to get accepted.

And to implement the disconnect, you'd just send the message from the JS to call a method in the server side channel to call the stop stream. This would look almost exactly like sending a message, you'd just pass in the name of the channel you want to remove.

Reply

Hi Chris. Thanks for your great tutorial!!

I want to keep the chatroom name bold. But if I reload the page, the chatroom name back to normal font-weight...
How can I keep that css??

Thank you,
K

Reply
Hi, chris. Thank you for taking me so far.
But i got a problem. you remember this

  $("#new_message").on "submit", (e) ->
    e.preventDefault()

but in my case, the 'e.preventDefauly()" does not work always. sometimes, it goes html like

Started POST "/chatrooms/1/messages"

And sometimes, it goes from coffees to job&channel... like

Started GET "/cable/" [WebSocket] for 127.0.0.1

Do you see any clear answer this problem? Help me:)
And why e.preventDefault() and following coffee codes do not work sometimes?
As i see log, when socket successfully connencted it works fine. But if there is no "Socket successful..." sentence, then it goes HTML way....why?!! :(
Reply
Hi Chris, I am hoping you can help me narrow down my error. I am trying to set up the app on a multi-tenancy app. I had all the models working before we started to use Action Cable, Active Job, and the more complex coffee script. I was able to add messages to the chatroom without any errors. But, now I am getting an error message where the tenant_id is NULL. I have tried to figure out where and how I would add the tenant_id to the code. Where do I add the tenant_id? Do I need to add it to the coffee script or the channel or the job? Or would I need to add it to multiple locations? 
Reply
please help me! 
i build a message app in my web following this tutorial.
but As i enter the chatroom & send message, then 

"ActionController::InvalidAuthenticityToken in MessagesController#create" error occurs.
I think it means "submit" acts as html form.

but As i enter the chatroom & refresh, then log tells me that 

"Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)" 
it means actioncable is working now.

so, user has to refresh as they enter the chatroom. it is rediculous, right?
what is the reason? Why actioncable does not work when entering the chatroom at the first place?
Reply

Hi Chris,

I really appreciate your tuts. It help to open my mind with action cable.
I am new to rails action cable. I wander if action can work in this case.
The channel only broadcast to client who subcribed for the channel with the stream.
How can it behaves like when I send a message to other user. The room just get created so I didn't reload or refresh to stream for that room. So how can I tranmmit the message to the receiver?

Thanks.

Reply

@chris, I just finished video #5 of the Chatrooms tutorial. Everything looks ok in terminal output, but when I hit 'enter' key after typing a message I still have to refresh browser to see the message appear. Here is repo: https://github.com/rmindigo/chat_demo_gorails Any ideas why message doesn't appear instantly? Terminal output below. Thanks!

[ActionCable] [User 12] Finished "/cable/" [WebSocket] for 127.0.0.1 at 2019-01-29 16:51:10 -0800
[ActionCable] [User 12] ChatroomsChannel stopped streaming from chatrooms:3
Started GET "/cable" for 127.0.0.1 at 2019-01-29 16:51:10 -0800
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2019-01-29 16:51:10 -0800
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 12], ["LIMIT", 1]]
[ActionCable] [User 12] Registered connection (Z2lkOi8vY2hhdC9Vc2VyLzEy)
[ActionCable] [User 12] Chatroom Load (0.3ms) SELECT "chatrooms".* FROM "chatrooms" INNER JOIN "chatroom_users" ON "chatrooms"."id" = "chatroom_users"."chatroom_id" WHERE "chatroom_users"."user_id" = ? [["user_id", 12]]
[ActionCable] [User 12] ChatroomsChannel is transmitting the subscription confirmation
[ActionCable] [User 12] ChatroomsChannel is streaming from chatrooms:3
[ActionCable] [User 12] ChatroomsChannel#send_message({"chatroom_id"=>3, "body"=>"see my message"})
[ActionCable] [User 12] Chatroom Load (0.3ms) SELECT "chatrooms".* FROM "chatrooms" WHERE "chatrooms"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
[ActionCable] [User 12] (0.1ms) begin transaction
[ActionCable] [User 12] SQL (0.8ms) INSERT INTO "messages" ("chatroom_id", "user_id", "body", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["chatroom_id", 3], ["user_id", 12], ["body", "see my message"], ["created_at", "2019-01-30 00:51:22.264530"], ["updated_at", "2019-01-30 00:51:22.264530"]]
[ActionCable] [User 12] (28.0ms) commit transaction
Message Load (0.4ms) SELECT "messages".* FROM "messages" WHERE "messages"."id" = ? LIMIT ? [["id", 49], ["LIMIT", 1]]
[ActionCable] [User 12] [ActiveJob] Enqueued MessageRelayJob (Job ID: b63d1b75-902b-47c9-b864-d6aec9495db6) to Async(default) with arguments: #<GlobalID:0x007f90e113e998 @uri=#<URI::GID gid://chat/Message/49>>
[ActiveJob] [MessageRelayJob] [b63d1b75-902b-47c9-b864-d6aec9495db6] Performing MessageRelayJob (Job ID: b63d1b75-902b-47c9-b864-d6aec9495db6) from Async(default) with arguments: #<GlobalID:0x007f90e1137f08 @uri=#<URI::GID gid://chat/Message/49>>
[ActiveJob] [MessageRelayJob] [b63d1b75-902b-47c9-b864-d6aec9495db6] Chatroom Load (0.2ms) SELECT "chatrooms".* FROM "chatrooms" WHERE "chatrooms"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
[ActiveJob] [MessageRelayJob] [b63d1b75-902b-47c9-b864-d6aec9495db6] User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 12], ["LIMIT", 1]]
[ActiveJob] [MessageRelayJob] [b63d1b75-902b-47c9-b864-d6aec9495db6] [ActionCable] Broadcasting to chatrooms:3: {:username=>"bratPitt", :body=>"see my message", :chatroom_id=>3}
[ActiveJob] [MessageRelayJob] [b63d1b75-902b-47c9-b864-d6aec9495db6] Performed MessageRelayJob (Job ID: b63d1b75-902b-47c9-b864-d6aec9495db6) from Async(default) in 3.17ms
[ActionCable] [User 12] ChatroomsChannel transmitting {"username"=>"bratPitt", "body"=>"see my message", "chatroom_id"=>3} (via streamed from chatrooms:3)

Reply

Hi Chris, I don't want to use Turbolinks in my app. Is there any way to replace the code?

Reply

Hi chris,
We will not use coffee script on Rails 6. So how can i send message from web browser over websocket to server (only by js).

Reply

Hi chris,
Isn't storing chat id is vulnerable to XSS?

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 82,329+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.