It’s been one year since Action Cable debuted at RailsConf 2015, and Sophie DeBenedetto is here to answer the question in the minds of many developers: what is it really like to implement “the highlight of Rails 5”? Sophie is a web developer and an instructor at the Flatiron School. Her first love is Ruby on Rails, although she has developed projects with and written about Rails, Ember and Phoenix.
Bạn đang xem: Rail là gì
Recent years have seen the rise of “the real-time web.” Web apps we use every day rely on real-time features—the sort of features that let you see new posts magically appearing at the top of your feeds without having to lift a finger.
While we may take those features for granted, they represent a significant departure from the HTTP protocol’s strict request-response pattern. Real-time web, by contrast, loosely describes a system in which users receive new information from the server as soon as it is available—no request required.
There are a number of strategies and technologies for implementing such real-time functionality, but the WebSocket protocol has been rising to prominence since its development in 2009. However, up until very recently, implementing the WebSocket protocol in Rails was difficult. There was no native support, and any real-time feature required integrating third party libraries and strategies like Faye or JavaScript polling. So let’s take a closer look at WebSockets and how Rails 5 has evolved to support real-time apps with Action Cable.
What are WebSockets?
WebSockets are a protocol built on top of TCP. They hold the connection to the server open so that the server can send information to the client, even in the absence of a request from the client. WebSockets allow for bi-directional, “full-duplex” communication between the client and the server by creating a persistent connection between the two.
Xem thêm: Hemochromatosis Là Gì – Những Biểu Hiện Khi Thừa Sắt
With the development of Action Cable and its recent integration into Rails 5, we now have a full-stack, easy-to-use implementation of WebSockets that follows the Rails design patterns we’ve come to rely on. The only question is why it took so long.
The Path to Real-Time Rails
In 2015, Rails’ benevolent-dictator-for-life DHH changed his tune about sockets. He started by acknowledging an important truth: that “dealing with WebSockets is a pain in the .” And although it wasn’t necessarily a pleasure to code, you could build real-time features into Rails with nothing more than Faye and Javascript polling. In fact, Campfire, Basecamp’s own chatting application, has been using polling for about a decade, and I’ve built compelling real-time features that way too.
But DHH knew there’s something lost without sockets. “If you can make WebSockets even less work than polling, why wouldn’t you do it?” Sure, polling met the needs of his team (and many others) for many years. But as more and more consumers and developers began demanding real-time functionality, and as newer frameworks like Phoenix arrived to meet that demand, Rails felt the need to deliver—and in fact, Action Cable draws some inspiration from Phoenix channels.
Xem thêm: Acceptance Là Gì – Acceptance Certificate Là Gì
It hasn’t been smooth sailing. I’ve followed the development of Action Cable closely, and before it was merged into Rails 5, I would say that it wasn’t easier than polling. But after a year of development, it’s very easy to implement, and it aligns nicely with the other design patterns we’ve become so comfortable with in Rails.
So, how does the “highlight” of Rails 5 work, and what’s it like to implement? Let’s take a closer look!
Introducing Action Cable
So what do we have to look forward to? Well, it’s what the docs call a “full-stack offering”: it provides both a client-side JavaScript framework, and a server-side Ruby framework. And because it integrates so tightly with Rails, we have access to all of our models from within our WebSocket workers, effectively layering Action Cable on top of our existing Rails architecture, including Active Record (or any other ORM).
Action Cable Under the Hood
Before we dive into some code, let’s take a closer look at how Action Cable opens and maintains the WebSocket connection inside our Rails 5 application.
Action Cable can be run on a stand-alone server, or we can configure it to run on its own processes within the main application server. In this post, we’ll be taking a look at the second approach.
Action Cable uses the Rack socket hijacking API to take over control of connections from the application server. Action Cable then manages connections internally, in a multithreaded manner, layering as many channels as you care to define over that socket connection.
For every instance of your application that spins up, an instance of Action Cable is created, using Rack to open and maintain a persistent connection, and using a channel mounted on a sub-URI of your main application to stream from certain areas of your application and broadcast to other areas.
Action Cable offers server-side code to broadcast certain content (think new messages or notifications) over the channel, to a subscriber. The subscriber is instantiated on the client-side with a handy JavaScript function that uses jQuery to append new content to the DOM.
Lastly, Action Cable uses Redis as a data store for transient data, syncing content across instances of your application.
Now that we have a basic understanding of how Action Cable works, we’ll build out a basic chatting application in Rails 5, taking a closer look at how Action Cable behaves along the way.
Building a Real-Time Chat App with Action Cable
Getting Started: Application Architecture
In this example, we’ll build a basic chatting application in which users can log in or sign up to create a username, then create a new chat room or choose from an existing chat room and start messaging. We’ll use Action Cable to ensure that our chat feature is real-time: any users in a given chat room will see new messages (their own and the messages of other users) appear in the chat, without reloading the page or engaging in any other action to request new content.
You can follow along below, check out the code for this project on GitHub, visit my deployment here or, deploy your own copy by clicking this button.
Starting a new Rails 5 app with Action Cable
At the time of this writing, Rails 5 was in Beta 3. So, to start a new Rails 5 app, we need to do the following.
First, make sure you have installed and are using Ruby 2.3.0. Then:
$ gem install rails –preSuccessfully installed rails-5.0.0.beta3Parsing documentation for rails-5.0.0.beta3Done installing documentation for rails after 1 seconds1 gem installedYou’ll also need to have Postgres and Redis installed in order to build this app. You can brew install redis and brew install postgres if you haven’t done so already.Now we’re ready to generate our new app!rails new action-cable-example –database=postgresqlThis will generate a shiny new Rails 5 app, complete with all kinds of goodies in our Gemfile. Open up the Gemfile and you’ll notice that we have:
The latest version of Rails
# Gemfilegem ‘rails’, ‘>= 5.0.0.beta3’, ‘Redis (which we will need to un-comment out): # Gemfile# gem ‘redis’, ‘~> 3.0’Puma (since Action Cable needs a threaded server):# Gemfilegem ‘puma’Make sure you’ve un-commented out the Redis gem from your Gemfile, and bundle install.
Domain Model
Our domain model is simple: we have users, chat rooms and messages.
A chat room will have a topic and it will have many messages. A message will have content, and it will belong to a user and belong to a chatroom. A user will have a username, and will have many messages.
The remainder of this tutorial will assume that we have already generated the migrations necessary to create the chat rooms, messages and users table, and that we have already defined our Chatroom, User and Message model to have the relationships described above. Let’s take a quick look at our models before we move on.
# app/models/chatroom.rbclass Chatroom # app/models/message.rbclass Message # app/models/user.rbclass User
Application Flow
We’ll also assume that our routes and controllers are up and running. A user can log in with a username, visit a chat room and create new messages via a form on the chat room’s show page.
Chuyên mục: Hỏi Đáp