视频地址:http://railscasts-china.com/episodes/action-cable-rails-5
- rails命令创建新app
$ rails new actioncable_app
1.1 在Gemfile文件中加入gem ‘jquery-rails’
1.2在app/assets/javascripts/application.js文件中加入启用jquery的注释
//= require jquery
//= require rails-ujs
- rails命令创建controller
$ rails generate controller rooms show
- 修改config/routes.rb
root to : 'rooms#show'
- rails命令创建model message
$ rails generate model message content:string
- rails命令db迁移
$ rails db:migrate
- 修改app/controllers/rooms_controller.rb
def show
@messages = Message.all
end
- 创建并修改app/views/messages/_message.html.erb
<div class = "message">
<p><%= message.content %></p>
</div>
- rails命令进入console创建新message
$ rails console
> Message.create! content: "Hello world!"
- 修改app/views/rooms/show.html.erb
<h1>Chat room</h1>
<div id = "messages">
<%= render @messages %>
</div>
- rails命令创建新channel
$ rails generate channel room speak
- 在config/routes.rb中添加actioncable服务端路径
mount ActionCable.server => '/cable'
- 打开app/assets/javascripts/cable.coffee中的@App
@App ||={}
App.cable = ActionCable.createConsumer()
- 修改app/asserts/javascripts/channels/room.coffee
speak: (message) ->
@perform 'speak', message: message
- 修改app/channels/room_channel.rb中的subscribed函数及speak函数
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_channel"
end
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">unsubscribed</span></span>
<span class="hljs-keyword">end</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">speak</span><span class="hljs-params">(data)</span></span>
ActionCable.server.broadcast <span class="hljs-string">'room_channel'</span>, <span class="hljs-symbol">message:</span> data[<span class="hljs-string">'message'</span>]
<span class="hljs-keyword">end</span>
end
- 修改app/asserts/javascripts/channels/room.coffee中的received方法
received: (data) ->
alert data['message']
这时打开调试服务器测试,会跳出js的alert动作
- 在app/views/rooms/show.html.erb中添加输入框,对应的数据传给room_speaker
<h1>Chat room</h1>
<div id=“messages”>
<%= render @messages %>
</div>
<form>
<lable>Say something:</lable><br>
<input type=“text” data-behavior=“room_speaker”>
</form>
- 在app/assets/javascripts/channels/room.coffee中添加js获取客户端输入,写在speak后面
App.room = App.cable.subscriptions.create “RoomChannel”,
connected: ->
# Called when the subscription is ready for use on the server
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
alert data[‘message’]
speak: (message) ->
@perform ‘speak’, message: message
$(document).on ‘keypress’, ‘[data-behavior~=room_speaker]’, (event) ->
if event.keyCode is 13 # return = send
App.room.speak event.target.value
event.target.value = ”
event.preventDefault()
- 修改app/channels/room_channel.rb中的speak函数,把获取的message存到数据库,把广播的功能移出到后续的job
def speak(data)
Message.create! content: data['message']
end
- 修改app/models/message.rb,添加after_create_commit方法,让消息入库后传给job广播
class Message < ApplicationRecord
after_create_commit { MessageBroadcastJob.perform_later self }
end
- rails命令创建新的job文件用来广播收到的消息
$ rails generate job MessageBroadcast
- 修改app/jobs/message_broadcast_job.rb文件
class MessageBroadcastJob < ApplicationJob
queue_as :default
def perform(message)
ActionCable.server.broadcast ‘room_channel’, message: render_message(message)
end
private
def render_message(message)
ApplicationController.renderer.render(partial: ‘messages/message’, locals: { message: message })
end
end
- 修改app/assets/javascripts/channels/room.coffee中的received方法
received: (data) ->
$('#messages').append data['message']
- 修改app/views/messages/_message.html.erb 添加cache
<% cache message do %>
<div class="message">
<p><%= message.content %></p>
</div>
<% end %>