Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Action cable rails5beta3

Action Cable Beispiel
Einfacher Chat
Rails 5

  • Be the first to comment

  • Be the first to like this

Action cable rails5beta3

  1. 1. ActionCable in Rails 5 15. Januar 2016
  2. 2. Überblick ● Websocket ● Erklärung der Basics am Beispiel einer kleinen Chat-Anwendung
  3. 3. Websocket ● Bidirektionale Kommunikation ● Benutzt auch Socket (tcp) ● Hat eigenes Protokoll – ws:// port 80 – wss:// port 443
  4. 4. Websocket Protokoll ● rfc6455 ● Opening Handshake ● Data Framing
  5. 5. Sec-WebSocket-Version ● Version of rfc 6455 – Section 4.1 ● 9. The request MUST include a header field with the name |Sec-WebSocket-Version|. The value of this header field MUST be 13. ● Keine Abwärtskompatibilität ● Aushandeln über Server Response (z.B. V 25 angefragt): HTTP/1.1 400 Bad Request Sec-WebSocket-Version: 13 Sec-WebSocket-Version: 8, 7
  6. 6. Opening Handshake - Client 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
  7. 7. Opening Handshake - Server HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
  8. 8. Sec-WebSocket-Key ● Client sendet Zufallszahl ● Server sendet Zufallszahl + GUID (fix) – SHA-1 → Base 64 ● Client verifiziert SHA-1 → Base64 gleiches Ergebnis? ● GUID: 258EAFA5-E914-47DA-95CA- C5AB0DC85B11
  9. 9. Javascript ● var Socket = new WebSocket(url, [protocol] ); ● Events: - open - message - error - close ● Methoden: – send() – close()
  10. 10. Rails Wrapper #= require action_cable #= require_self #= require_tree ./channels # @App ||= {} App.cable = ActionCable.createConsumer()
  11. 11. Server ● Vor Rails 5 eigener Server: # cable/config.ru require ::File.expand_path('../../config/environment', __FILE__) Rails.application.eager_load! require 'action_cable/process/logging' run ActionCable.server #!/bin/bash bundle exec puma -p 28080 cable/config.ru
  12. 12. Server ● Routing Rails.application.routes.draw do # Serve websocket cable requests in-process mount ActionCable.server => '/cable' resources :messages, only: [:index] resources :sessions, only: [:new, :create] root 'sessions#new' end
  13. 13. Example ● Rails 5 Chat via ActionCable ● Rails 5.0.0.beta3 ● Setup Rails
  14. 14. Session Controller ● Session Controller (root 'session#new') class SessionsController < ApplicationController def create cookies.signed[:username] = params[:session][:username] redirect_to messages_path end end ● View = form_for :session, url: sessions_path do |f| = f.label :username, 'Enter a username' br = f.text_field :username br = f.submit 'Start chatting'
  15. 15. Messages (Chat) Controller Keine Logik in Controller, nur View: div p | Signed in as @ =cookies.signed[:username] | . #messages br br = text_field_tag :body, '', id: 'chat-speak'
  16. 16. ApplicationCable (Server) ● app/channels/application_cable/channel.rb – Similar to ApplicationController ● app/channels/application_cable/connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = cookies.signed[:username] end end end
  17. 17. Schönerer View .panel.panel-info .panel-heading h3.panel-title | Signed in as .panel-body =cookies.signed[:username] .panel.panel-success .panel-heading h3.panel-title | Conversation goes here .panel-body table.table thead tr th | User th | Message tbody#messages .panel.panel-default .panel-heading h3.panel-title | Type something .panel-body = text_field_tag :body, '', id: 'chat-speak' .panel-footer
  18. 18. Channels / ChatChannel ● app/channels/chat_channel class ChatChannel < ApplicationCable::Channel def subscribed stream_from 'messages' # 'messages' is name of queue end def unsubscribed end def speak(data) # sends a message to all subscribers ActionCable.server.broadcast('messages', message: render_message(data['message'])) end private def render_message(message) ApplicationController.render(partial: 'messages/message', locals: {message: message, username: current_user})
  19. 19. Javascript App.chat = App.cable.subscriptions.create "ChatChannel", 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) -> $('#messages').append(data.message) speak: (msg)-> @perform 'speak', message: msg $(document).on 'keypress', '#chat-speak', (event) -> if event.keyCode is 13 App.chat.speak(event.target.value) event.target.value = "" event.preventDefault()
  20. 20. Live Demo ● Einfacher Chat ● Redis integration checken ● Console öffnen ActionCable.server.broadcast 'messages', message: '<tr><td>Konsole</td><td>Externe Nachricht</td></tr>'

×