ActionCable in Rail5 实战笔记

rails5 ActionCable in chatroom, 为之后开发狼人多人游戏做准备

  • 整个流程
    After rails new chat and bundle install, we add some related in Gemfile, so now it will look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
source 'https://rubygems.org'

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

gem 'sqlite3'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'puma'
gem 'uglifier', '>= 1.3.0'

group :development, :test do
gem 'byebug'
gem 'spring'
gem 'web-console', '~> 2.0'
end

[1] in routes.rb, we set the root page to be

1
root ‘sessions#new’

which means that it will first find the SessionsController’s new method and implement it. We know in rails that when it runs a controller method, it will also render the corresponding views html.erb in view folder. Thus the views/sessions/new.html.erb will be first rendered.

Further observing in routes.rb:

1
2
3
4
5
Rails.application.routes.draw do
resources :messages, only: [:index, :create]
resources :sessions, only: [:new, :create]
root 'sessions#new'
end

we find the use of resources, which means we treat those objects as RESTFUL as we could, those objects in their controllers will have all seven methods like new, create, update, destroy and so on which corresponds to the Http Verbs like post, get and so on.

Then, we look at the new.html.erb

1
2
3
4
5
<%= form_for :session, url: sessions_path do |f| %>
<%= f.label :username, 'Enter a name' %><br/>
<%= f.text_field :username %> <br>
<%= f.submit 'Start chatting' %>
<% end %>

where :session is the name for this form, when in use in SessionsController, we obtain the information in this form by

1
cookies.signed[:username] = params[:session][:username]

And url: sessions_path is for directing the action to SessionsController#create.

In MessagesController.rb

we use index to render the view

1
2
3
4
5
6
7
8
9
10
11
Signed in as @<%= cookies.signed[:username] %>.
<br><br>

<div id="messages"></div>
<br><br>

<%= form_for :message, url: messages_path, remote: true, id: messages-form do |f| %>
<%= f.label :body, 'Enter a message:' %> <br>
<%= f.text_field :body %> <br>
<%= f.submit 'Send message' %>
<% end %>

where the cookies are carrying the parameters we need in another controller, while the empty div will eventually be filled with previous content. As for the form, it will pretty similar as the SessionsController#new.

  • here we use remote: true, which is calling with Ajax. In usual case, we will need to specify the partial js file we want to implement in MessagesContrller#create method. * But, here we just want it to reload again without refreshing the page.

ActionCable

ActionCable uses Redis for publishihng and subscribing to the messages, so we need to configure Redis in config/redis/cable.yml. You will need Redis installed and running for ActionCable to work.

Redis

reds is a key-value store, often referred to as a NoSQL database. Key features are that: [1] the data can be retrieved by key later in use. [2] the key-value will be stored permanently.

1
2
3
4
SET server:name “fido”
GET server:name
DEL server:name
INCR count

Compared with

1
2
3
x = GET count
x = x + 1
SET count x

we choose to use INCR because it is a atomic operation which will work as expected if multiple users want to access this value.

1
2
EXPIRE server:name 120 //after 120s this value will vanish
TTL server:name // obtain after how long it will vanish

List operation

RPUSH, LPUSH, LLEN, LRANGE, LPOP, RPOP

Set operation

SADD, SREM, SISMEMBER, SMEMBERS, SUNION
where SMEMBERS returns a list of all members of this set.

Sorted Set

ZADD, ZRANGE

Hashes

HSET, HGETALL, HMSET, HGET, HINCRBY, HDEL like

1
2
HMSET user:1001 name "Mary Jones" password "hidden" email "[email protected]"
HGETALL user:1001

Adding our MessagesChannel

1
2
3
4
5
6
# app/channels/messages_channel.rb
class MessagesChannel < ApplicationCable::Channel
def subscribed
stream_from 'messages'
end
end

whenever a client subscribes to MessageChannel, the #subscribed method will be called, which starts streaming anything you broadcast to the “messages” stream.

Future learning

一起加油!