Uma visão superficial sobre os cabos de ação do Rails
Feliz aquele que transfere o que sabe e aprende o que ensina.
Cora Coralina
Since mar/2016 - Enterprise Applications
@devjoaogustavo
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
@current_user = find_verified_user
Rails.logger.info "Mais uma conexão: total de #{ActionCable.server.connections.size + 1}"
end
def disconnect
Rails.logger.info "Menos uma conexão: total de #{ActionCable.server.connections.size}"
end
private
def find_verified_user
if current_user = User.find_by(id: cookies.signed[:user_id])
current_user
else
reject_unauthorized_connection
end
end
end
end
# app/config/initializers/warden_hooks.rb
Warden::Manager.after_set_user do |user,auth,opts|
scope = opts[:scope]
auth.cookies.signed["#{scope}.id"] = user.id
end
class MessagesChannel < ApplicationCable::Channel
def subscribed
end
def unsubscribed
end
def receive(data)
end
end
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
App.messages = App.cable.subscriptions.create('messages', {
connect: function() {},
disconnect: function() {},
subscribed: function() {},
unsubscribed: function() {},
received: function() {}
});
class MessagesChannel < ApplicationCable::Channel
def subscribed
stream_from 'messages'
end
end
class CommentsChannel < ApplicationCable::Channel
def subscribed
post = Post.find(params[:id])
stream_for post
end
end
CommentsChannel.broadcast_to(@post, @comment)
class MessagesController < ApplicationController
def create
message = Message.create!(content: params[:content])
ActionCable.server.broadcast('messages', { message: message.content })
...
end
end
App.messages = App.cable.subscriptions.create('messages', {
received: function(data) {
$('#content').val('');
return $('#messages').append(this.addMessage(data));
},
addMessage: function(data) {
return '<p><b>User: </b>'+data.message+'<p>';
}
});
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from "chat_#{params[:room]}"
end
end
App.users = App.cable.subscriptions.create({channel: 'ChatChannel', room: 'bla'}, {
received: function(data) {
return $('#users').append(this.addUser(data.username));
},
addUser: function(data) {
return '<p>'+data+'</p>';
}
});
ChatChannel.broadcast_to("chat_#{room}", sent_by: 'Cabra', body: 'Chat joiado!')
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from "chat_#{params[:room]}"
end
def receive(data)
ActionCable.server.broadcast("chat_#{params[:room]}", data)
end
end
App.chatChannel = App.cable.subscriptions.create({channel: "ChatChannel", room: "bla"}, {
received: function(data) {}
});
App.chatChannel.send({
sent_by: "Paul",
body: "This is a cool chat app."
});
development:
adapter: async
test:
adapter: async
production:
adapter: redis
url: redis://127.0.0.1:6379
config.action_cable.allowed_request_origins = ['http://localhost:3000']
config.action_cable.disable_request_forgery_protection = true
<%= action_cable_meta_tag %>
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer("ws://localhost:28080");
}).call(this);
class Application < Rails::Application
config.action_cable.mount_path = '/cable'
end
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
end
# cable/config.ru
require_relative 'config/environment'
Rails.application.eager_load!
run ActionCable.server
#!/bin/bash
bundle exec puma -p 28080 cable/config.ru