Action Cable 설정에서 실패

하는 짓


다음 글과 영상 제작 채팅 기능을 참고하세요.
Rails5+Action Cable로 제작!간단한 채팅 소프트웨어(DHH 프레젠테이션 비디오)
0부터 시작하는 Rails 채팅 애플리케이션[튜토리얼]
실시간 채팅 기능 제작 중 걸려 넘어진 일도 메모로 공유한다.
지적과 건의가 있으면 메시지를 남겨주세요.

하고 싶은 일


자신(current user)과 다른 사람으로 표현 방법 바꾸기

채널 만들기

$ rails g channel chatroom speak
    create  app/channels/chatroom_channel.rb
    create  app/assets/javascripts/channels/chatroom.coffee

좌절된 일


· chatroom_channel.rb에서render로 호출_post.html.erb하면 [ActionView::Template::Error - undefined method 'id' for nil:NilClass]라고 부른다.→ 채널 렌더에서 얻은 값이 없기 때문current_user

코드 목록


routes.rb
Rails.application.routes.draw do
  root to: 'toppages#index'
  # (省略)

  resources :chatrooms do
    member do
      get :users
    end
  end

  mount ActionCable.server => '/cable'
end
posts/_post.html.erb
<% unless post.user_id == current_user.id %>
  <p style="color:blue;"><%= post.content %></p>
<% else %>
  <p style="color:red;"><%= post.content %></p>
<% end %>
chatroom_channel.rb
class ChatroomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chatroom_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak(data)
    message = Post.create! content: data['message'], user_id: data['user_id'], chatroom_id: data['room_id']
    template = ApplicationController.renderer.render(partial: 'posts/post', locals: { post: message })
    ActionCable.server.broadcast 'chatroom_channel', message: template
  end
end
chatroom.coffee
# クライアントサイドの処理を受け持つチャンネ
App.chatroom = App.cable.subscriptions.create "ChatroomChannel",
  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) ->
    $('#posts').append data['message']


    # Called when there's incoming data on the websocket for this channel

  speak: (content, data_user, data_room) ->
    @perform 'speak', message: content, user_id: data_user, room_id: data_room


document.addEventListener 'DOMContentLoaded', ->
  input = document.getElementById('chat_input') 
  data_user = input.getAttribute("data_user")
  data_room = input.getAttribute("data_room")
  button = document.getElementById('chat_button')
  button.addEventListener 'click', ->
    content = input.value
    App.chatroom.speak(content, data_user, data_room)
    input.value = ''
    return
  return

까닭


채널은 세션을 사용할 수 없다고 합니다.
(sessions helper에 current user가 정의되어 있습니다.)

해결책


채널에서 쿠키를 사용할 수 있기 때문에 쿠키에서 사용자 정보,current사용자 변수를 대체합니다.
주로 여기.의 글을 참고하였다.

쿠키 정보current에서사용자 제작


channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    protected

    def find_verified_user
      if verified_user = User.find_by(id: session['user_id'])
        verified_user
      else
        reject_unauthorized_connection
      end
    end

    def session
      cookies.encrypted[Rails.application.config.session_options[:key]]
    end
  end
end
chatroom_channel.rb
# (省略)

  def speak(data)
    message = Post.create! content: data['message'], user_id: data['user_id'], chatroom_id: data['room_id']
    template = ApplicationController.renderer.render(partial: 'posts/post', locals: { post: message, current_user: current_user }) # current_user変数にconnection.rbで取得したcurrent_userを設定
    ActionCable.server.broadcast 'chatroom_channel', message: template
  end

관련 링크


DOMContentLoaded에서 turbolinks:load로 변경
Action Cable로 id 전달

참조 링크


Rails5의 Action Cable로 간단한 채팅 만들기~ 모델에 따라 채널을 듣는 방법~

좋은 웹페이지 즐겨찾기