📜 ⬆️ ⬇️

Live Chat & ActionCable

I want to publish a short note on how to integrate, recently released, ActionCable into your Ruby on Rails project using the example of a live chat. I will not go deep into how ActionCable works , I will just give a small example of use.

Training


First of all, add actioncable and puma to Gemfile :

gem 'actioncable', github: 'rails/actioncable' gem 'puma' 

ActionCable will be launched by a separate process from the main application. Therefore, we will use the multi-threaded Puma web server.
')

Chat architecture


The user will enter his nickname on the main page, after which we will write it in the cookie and send it to the chat page.

Add a couple of routes in the config / routes.rb :

 resources :messages, only: [:index, :create] resources :sessions, only: [:new, :create] 

Create controllers with action games. Record nickname in cookies:

 # app/controllers/sessions_controller.rb class SessionsController < ApplicationController def create cookies.signed[:username] = params[:session][:username] redirect_to messages_path end end 

User authorization forms app / views / sessions / new.html.slim:

 = form_for :session, url: sessions_path do |f| p = f.label :username, '  ' p = f.text_field :username p = f.submit '' 

In the chat itself for the time being we will simply send 200 in response to the printed message:

 # app/controllers/messages_controller.rb class MessagesController < ApplicationController def create head :ok end end 

View app / views / messages / index.html.slim:

 p = cookies.signed[:username] p #messages p = form_for :message, url: messages_path, remote: true, id: 'messages-form' do |f| p = f.label :body, ' :' p = f.text_field :body p = f.submit '' 

The message will be sent by AJAX to the server.

Configuring ActionCalbe


Create three classes that will be responsible for integrating with ActionCable.

 # app/channels/application_cable/connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base end end # app/channels/application_cable/channel.rb module ApplicationCable class Channel < ActionCable::Channel::Base end end # app/channels/messages_channel.rb class MessagesChannel < ApplicationCable::Channel def subscribed stream_from 'messages' end end 

Do not forget to add the created directories in autoload_paths . Now, everyone who subscribes to the MessagesChannel channel will be able to receive messages on the corresponding stream defined in the subscribed method, i.e. - messages .

ActionCable provides messaging through Redis. We assume that you have it already installed. We need to set up a connection with it in config / redis / cable.yml :

 development: &dev :url: redis://localhost:6379 :host: localhost :port: 6379 :timeout: 1 :inline: true test: *dev production: *dev 

Now configure Puma:

 # cable/config.ru require ::File.expand_path('../../config/environment', __FILE__) Rails.application.eager_load! require 'action_cable/process/logging' run ActionCable.server 

We will launch Puma on port 34523, why not ...

 # /bin/bash bundle exec puma -p 34523 cable/config.ru 

Now the cougar is launched by the command ./bin/cable .

Sending messages to the general chat



Few update app / controllers / messages_controller.rb :
 class MessagesController < ApplicationController def create ActionCable.server.broadcast 'messages', message: params[:message][:body], username: cookies.signed[:username] head :ok end end 


The most important thing is to subscribe to the channel. Create two coffee files (do not forget to recompile them):

 #app/assets/javascripts/channels/messages.coffee App.messages = App.cable.subscriptions.create 'MessagesChannel', received: (data) -> $('#messages').append("<p><b>[#{data.username}]:</b> #{data.message}</p>") #app/assets/javascripts/channels/index.coffee #= require cable #= require_self #= require_tree . @App = {} App.cable = Cable.createConsumer('ws://127.0.0.1:34523') 

That's all.
As always, a small project - https://github.com/lon10/live-chat

Source: https://habr.com/ru/post/264589/


All Articles