First of likely a 3 part series, demonstrating setting up, implementing, testing and deploying Action Cable in a Rails 4 project with AngularJS
Let me first start off by saying Action Cable is cool - like really cool. If you're unfamiliar with Action Cable, all you need to know is that it will make WebSockets a first-class citizen for rails 5, thus allowing for scalable real-time updates.
Luckily for me, I got to implement a feature with Action Cable at work for an exchange we're building for real-time monitoring and updates. And while that implementation is a little more robust, this series of posts will hopefully demonstrate the power of Action Cable, especially coupled with a front-end framework, and help some folks get started with Action Cable.
First, a shoutout to where I got most of my help from.
Alright, now we need to setup the project to handle Action Cable. First, let's add Action Cable and foreman as dependencies to our project and run $ bundle install
. I'll come back to why we need foreman
a little later. I'm also going to use Puma for my application server in preparation for a deployment down the road.
#Gemfile
gem 'actioncable', github: 'rails/actioncable', branch: 'archive'
gem 'foreman'
gem 'puma'
As of this article (~Oct. 2015), Action Cable relies on redis's pubsub feature to route messages back and forth over the WebSocket cable connection, so let's install redis and start the redis server locally. In a future post, I'll touch on deploying and configuring redis via ansible.
// assuming you're using homebrew
$ brew install redis
$ redis-server
Now that our redis server is running, let's configure Action Cable to connect to our redis server. By default, ActionCable::Server::Base
will look for a configuration file in config/redis/cable.yml
.
# config/redis/cable.yml
local: &local
:url: redis://localhost:6379
:host: localhost
:port: 6379
:timeout: 1
:inline: true
development: *local
test: *local
Great, now Action Cable has a configuration to load to connect to our redis server. But we're going to run Action Cable as a separate process than our main rails application. To do this, I'm going to use foreman
to manage both our main web process and our Action Cable process. So first, let's create a rackup file for our Action Cable process.
# cable/config.ru
require ::File.expand_path('../../config/environment', __FILE__)
Rails.application.eager_load!
require 'action_cable/process/logging'
run ActionCable.server
Next, I'll create my Procfile
to tell foreman about our additional process. In a later post, we'll pull out these hardcoded variables exported via foreman and set in ansible.
// Procfile
web: bundle exec rails s -p 3000 -e development Puma
action_cable: bundle exec puma -p 28080 cable/config.ru
Lastly, we need to create our Connection (to handle authentication) and Channel class (to house logic shared across Channels). For basic setup, this is all you need:
# 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
OK. So if we've done everything correctly, running foreman start
will boot up our 2 processes and if we curl our Action Cable server with $ curl -XGET localhost:28080?message='hello'&user='me'
, we should see a request made in the foreman process logs.
Gook luck!