使用 Rails 的 Action Cable 创建聊天
介绍
在本教程中,我们将探索 Ruby on Rails 的两个新功能 - Action Cable和Active Job。毫无疑问,Action Cable 是两者中更令人兴奋的。它集成了WebSocket通信协议,与其祖先 HTTP 相比,它提供了一些很棒的新功能,将为您提供许多构建事物的新想法。Rails 可能是第一个采用和实现 WebScoket 协议的成熟框架,因此您只能想象使用它可以构建什么的可能性!
为了最好地展示 ActionCable、WebSocket 和 Active Job 的功能,我们将使用 Ruby on Rails 5 构建一个聊天室
HTTP 和 Websockets
在 HTTP 中,服务器和客户端之间的连接寿命很短:客户端向服务器请求资源,与服务器建立连接,并将请求的资源(无论是 JSON、HTML、XML 还是某种文件)作为响应流式传输到客户端。然后,连接关闭。但客户端如何知道服务器是否有新数据或更新数据?通常,HTTP 会使用长轮询,其中客户端会“询问”服务器在给定的时间间隔内是否有新内容。
与 HTTP 不同,WebSockets 是一种协议,它使客户端和服务器能够保持开放的连接,从而使它们能够直接在彼此之间传输数据。客户端订阅服务器中的开放 websocket 连接,当有新信息时,服务器会广播数据,订阅的客户端会接收数据。这样,服务器和客户端都知道数据的状态,并且可以轻松地在发生更改时同步更改。
ActionCable 如何发挥作用?
由于 Rails 控制器是专门为处理 HTTP 请求而构建的,因此 Rails 设计了一种不同的方法来处理其与 WebSockets 的集成。Rails 5 应用程序在应用程序目录中有一个名为 channels 的新目录。Channels 通过封装有关特定单元工作(例如聊天消息或通知)的逻辑,充当 WebSocket 请求的控制器。客户端可以订阅这些通道,以便从一个或多个通道传输数据。
安装 ActionCable
Action Cable 是一项新功能,需要您拥有最新版本的 Rails 5。Rails 5 的先决条件之一是您已安装 Ruby 2.2.4(及更高版本)及其开发工具包。截至 2016 年 3 月 11 日,最新稳定版本是 Rails 5 beta3。为了获得它,您需要使用以下选项安装 rails gem:
gem install rails --pre --no-ri --no-rdoc
PostgreSQL
Action Cable 需要PostgreSQL作为其适配器。您需要在操作系统上安装并配置它,然后才能继续本教程(继续,我们会等待)。
使用 pgsql 创建新的 Rails 应用程序
创建新的 Rails 应用程序时,您需要将其指定为适配器,以便新应用程序不会具有默认的 SQLite。
rails _5.0.0.beta3_ new chatapp --database=postgresql
创建应用程序并配置database.yml文件以匹配您的 PostgreSQL 设置后,您就可以继续并创建一个空数据库:
cd chatapp
rake db:create
奠定基础
您可能已经从新应用程序的名称中猜到了,我们将构建一个非常简单的聊天程序,利用 Action Cable 的强大功能。以下是它在几个伪代码步骤中的工作方式:
- 创建一个名为room_channel的服务器端 websocket 通道,该通道将具有客户端订阅和取消订阅的方法,以及向客户端发送数据的方法。
- 使用 JavaScript(本例中为 CoffeeScript)创建通道的客户端表示,称为RoomChannel(注意命名约定)。它将订阅服务器端通道,并具有在连接/断开服务器时触发的方法以及处理、发送和接收数据的方法。
- 创建一个Rails 作业,将要创建的新消息排入数据库中,并在创建后通过 websocket 通道将其广播回来。
首先,让我们开始为聊天室搭建一个简单的控制器。它将包含聊天本身的视图。
rails g controller rooms show
控制器和动作已经完成,所以让我们把它们作为应用程序的根:
#config/routes.rb
Rails.application.routes.draw do
root to: 'rooms#show'
接下来,我们将创建一个模型,正如您可能猜到的那样,它被称为消息,并且它将具有一个用于存储实际消息的内容属性。
rails g model message content:text
并将其迁移到数据库中。请注意,在 Rails 5 中,您可以使用rails执行 rake 任务。
rails db:migrate
模型准备好后,让我们将所有消息添加到显示动作中。
#app/controllers/rooms_controller.rb
class RoomsController < ApplicationController
def show
@messages = Message.all
end
end
控制器和模型已经完成,是时候转到视图了。
首先,是时候删除rooms#show的脚手架视图并将其替换为:
<h1>Chat room</h1>
<div id="messages">
<%= render @messages %>
</div>
<form>
<label>Say something:</label><br>
<input type="text" data-behavior="room_speaker">
</form>
其次,让我们在 views 文件夹中创建一个消息文件夹,并创建用于呈现单个消息的部分:
# app/view/messages/_message.html.erb
<div class=“message”>
<p><%= message.content %></p>
</div>
render @messages将自动在views/messages目录中查找_message.html.erb部分来显示每条消息,这样我们就不必编写任何额外的东西 - 它不能比这更干燥!
另外,请确保你的applicaton.js包含 JQuery:
// app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
创建频道
到目前为止,都是标准的 Rails 内容。是时候转到有趣的部分了:创建您的第一个 ActionCable 频道。
我们需要做的第一件事是在应用程序中启用 ActionCable。只需两个简单的步骤即可完成:
- 将其挂载到routes.rb中。
#config/routes.rb
# Serve websocket cable requests in-process
mount ActionCable.server => '/cable'
- 在cable.coffee中初始化它
#= require action_cable
#= require_self
#= require_tree ./channels
#
@App ||= {}
App.cable = ActionCable.createConsumer()
您还需要检查app/views/layouts/application.html.erb的头部部分是否有<%= action_cable_meta_tag %>。
Rails 引入了一个用于生成通道的新生成器,让我们运行它并看看它的作用:
rails g channel room speak
运行此程序将生成两个文件;一个位于app/assets/javascripts/channels/room.coffee 的javascript 文件和一个位于app/channels/room_channel.rb的 ruby 文件。
我们先来分析一下ruby文件:
#app/channels/room_channel.rb
class RoomChannel < ApplicationCable::Channel
def subscribed
# stream_from "some_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def speak
end
end
订阅方法是客户端连接到频道时调用的默认方法,通常用于“订阅”客户端以监听更改。发言操作是我们在运行生成器时创建的自定义操作。 它将用于从其客户端表示中接收数据。
#app/assets/javascripts/channels/room.coffee
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) ->
# Called when there's incoming data on the websocket for this channel
speak: ->
@perform 'speak'
在 JavaScript 文件中,客户端通过App.room = App.cable.subscriptions.create "RoomChannel"订阅服务器。有三种默认方法:connected、disconnected(您可能已经猜到了,它处理连接的状态)和 received(它将处理从服务器端接收的数据)。JavaScript文件中的talk方法将用于将数据发送到其服务器端表示。
输入App.cable将显示 ActionCable 在客户端的实际表示。App.room是我们刚刚创建的通道。通过输入App.room.speak ,我们从 room.coffee 文件中调用了 talk() 函数,该函数随后将数据传输到room_channel中的talk方法。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~