ActionCable is an upcoming component of Ruby on Rails 5.0 - it is the websockets framework wich aims to simplify the addition of realtime features. In this post, we'll explain the integration between ember.js and actioncable through a simple example app: a very basic chat where people can pick a username and start posting to a public chatroom. We'll be introducing the new ember-cable addon, which makes it dead-simple to add ActionCable's power to your Ember apps.
ActionCable works also with Rails 4.2 and we will use ember-cli-rails to integrate ember into rails. Please follow our previous tutorial on how to setup ember and rails
This tutorial will take you 30 minutes. If you are too busy to read how to build it from scratch, jump to this repository with the complete code.
Setting up threaded server
In this example we will use puma, a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. First, make sure Puma is in your Gemfile
gem 'puma'
then install dependencies
$ bundle install
and run the server to check that everything's working.
$ rails s
=> Booting Puma
=> Rails 4.2.5 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Puma 2.15.3 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://localhost:3000
Setting up ActionCable
Now that we have everything else in place, let’s set up ActionCable. Add the actioncable
gem into Gemfile
gem 'actioncable', github: 'rails/actioncable'
then install dependencies
$ bundle install
Now we need to extend ApplicationCable::Connection
and ApplicationCable::Channel
- the latter will be the superclass for our own channel classes. Rails will hopefully generate these stubs for us, once the final version is released.
# 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
ActionCable uses Redis for publishing and subscribing to channels, so we need to configure it.
# config/redis/cable.yml
local: &local
:url: redis://localhost:6379
:host: localhost
:port: 6379
:timeout: 1
:inline: true
development: *local
test: *local
The last step to complete ActionCable setup on backend is routing configuration.
# config/route.rb
Rails.application.routes.draw do
# keep this on top
match '/websocket', to: ActionCable.server, via: [:get, :post]
mount_ember_app :frontend, to: "/"
end
Create backend channel
We need to create a channel in order to manage subscriptions:
# app/channels/messages_channel.rb
class MessagesChannel < ApplicationCable::Channel
def subscribed
stream_from 'messages'
end
def receive(data)
ActionCable.server.broadcast 'messages', data
end
end
Setting up ember-cable
The next step is to add ember-cable to our ember application. Following the documentation let's install it with:
ember install ember-cable
and running npm install
command.
Create chat component
Now that we have a support for ember cable in both backend and frontend, we can create a simple component to test it all together. Change to frontend directory and type:
ember g component simple-chat
app/components/simple-chat.js
import Ember from 'ember';
export default Ember.Component.extend({
cableService: Ember.inject.service('cable'),
messages: [],
username: 'guest',
body: 'message body',
setupSubscription: Ember.on('init', function () {
var consumer = this.get('cableService').createConsumer(
'ws://localhost:3000/websocket',
);
var subscription = consumer.subscriptions.create('MessagesChannel', {
received: (data) => {
this.get('messages').pushObject({
username: data.username,
body: data.body,
});
},
});
this.set('subscription', subscription);
}),
actions: {
sendMessage() {
this.get('subscription').send({
username: this.get('username'),
body: this.get('body'),
});
},
},
});
app/templates/components/simple-chat.hbs
{{input value=username}}
{{input value=body}}
<button {{action 'sendMessage'}}>
Send
</button>
{{#each messages as |message|}}
<p>{{message.username}} -> {{message.body}}</p>
{{/each}}
Let's chat!
Now that you have a chat component, why not try and use it? Just add it to application.hbs
template, then start the app, open it in many browser windows and enjoy chatting!
I hope I’ve peaked your interest with this article. The code used in this article is available here. Feel free to join the discussion in the comments.
Powering your Ember apps with Rails' ActionCable via @safeforge
Click to tweet