Action Cableの設定でつまずいたこと

##行っていること
以下の記事や動画を参考にチャット機能を作成しています。
[Rails 5 + ActionCableで作る！シンプルなチャットアプリ（DHH氏のデモ動画より）](https://qiita.com/jnchito/items/aec75fab42804287d71b)
[0から手を動かして作るRailsチャットアプリ【チュートリアル】](https://www.youtube.com/watch?v=WCsgcp5dg7M)

リアルタイムでのチャット機能を作成する際につまずいたことを、備忘録も兼ねて共有します。
ご指摘やアドバイスがありましたらコメントよろしくお願いします。

##やりたいこと
自分(current_user)と他の人で表示方法を変える
<img width="539" alt="スクリーンショット 2020-01-24 17.56.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292027/e4d06bc4-7a89-638b-7c55-e16c028d7f95.png">


##チャンネルの作成
```
$ rails g channel chatroom speak
    create  app/channels/chatroom_channel.rb
    create  app/assets/javascripts/channels/chatroom.coffee
```

##つまずいたこと
・`chatroom_channel.rb`から`_post.html.erb`をrenderで呼び出そうとすると、`[ActionView::Template::Error - undefined method 'id' for nil:NilClass]` と言われる。→channelからrenderした際に`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
```

```erb: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
```

##原因
channelからは sessionを使うことが出来ないそうです。
(sessions_helperでcurrent_userを定義している。)


##解決方法
channelからcookieは使うことができるそうなので、cookieからユーザー情報を取ってきて、current_user変数に代入。
主に[こちら](http://blog.aqutras.com/entry/2016/04/27/210000)の記事を参考にしました。

### cookieの情報からcurrent_userの作成


```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へ変更](https://qiita.com/kazama0119/items/d52fbd918f7e1150f4b2)
・[Action Cableへのidの受け渡し](https://qiita.com/kazama0119/items/02c5c3a354ba82399362)


## 参考リンク
・[Rails5のActionCableで簡易チャットの作成 ~モデルに応じたチャンネルを聴講する方法~](http://blog.aqutras.com/entry/2016/04/27/210000)