開発環境
rails
5.1.7
ruby
2.4.0
devise導入済
作成する
gem 'jquery-rails'
...
//
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require jquery ←追加
//= require jquery_ujs ←追加
//= require_tree .
...
$ bundle
モデル作成
roomモデル、entryモデル、direct_messageモデルを作成
$ rails g model room name:string
$ rails g model entry user:references room:references
$ rails g model DirectMessage user:references room:references name:string
$ rails db:migrate
モデル編集
...
has_many :entries
has_many :direct_messages
has_many :room, through: :entries
...
...
has_many :entries
has_many :direct_messages
has_many :users, through: :entries
...
コントローラ作成
$ rails g controllers Rooms show
ルーティングの設定
root 'users#index'
devise_for :users
resources :users
resources :rooms
これでrails s
してサーバーをたちあげ、http://localhost:3000
へアクセスしてみる。
成功したらおk
Usersコントローラを編集
class UsersController < ApplicationController
before_action :authenticate_user!
def index
@users = User.all
end
def show
@user = User.find(params[:id])
@currentUserEntry = Entry.where(user_id: current_user.id)
unless @user.id == current_user.id
@currentUserEntry.each do |cu|
@userEntry.each do |u|
if cu.room_id == u.room_id then
@isRoom = true
@roomId = cu.room_id
end
end
end
unless @isRoom
@room = Room.new
@entry = Entry.new
end
end
end
end
users/index/html.erbの作成
<h3>ユーザー一覧</h3>
<h2><%= @user.name %></h2>
<% unless @user.id == current_user.id %>
<% if @isRoom == true %>
<%= link_to "チャットをする", room_path(@roomId) %>
<% else %>
<%= form_for @room do |f| %>
<%= fields_for @entry do |e| %>
<%= e.hidden_field :user_id, :value => @user.id %>
<% end %>
<%= f.submit 'チャットを始める' %>
<% end %>
<% end %>
<% end %>
Roomsコントローラ編集
class RoomsController < ApplicationController
before_action :authenticate_user!
def show
@room = Room.find(params[:id])
# present?の戻り値はboolean, よってtrueの場合、
if Entry.where(:user_id => current_user.id, :room_id => @room.id).present?
@direct_messages = @room.direct_messages
@entries = @room.entries
else
redirect_back(fallback_location: root_path)
end
end
def create
@room = Room.create(:name => "DM")
@entry1 = Entry.create(:room_id => @room.id, :user_id => current_user.id)
@entry2 = Entry.create(params.require(:entry).permit(:user.id, :room_id).merge
redirect_to room_path(@room_id)
end
end
### rooms/show.html.erbの作成
erb:app/views/rooms/show.html.erb
<h1><%= @room.name %></h1>
<h4>参加者</h4>
<% @entries.each do |e| %>
<%= link_to e.user.name, user_path(e.user_id) %>
<br />
<% end %>
<h1>Chat room</h1>
<form>
<label> Say somethig:</label><br />
<input type="text" id="chat-input" data-behavior="room_speaker>
</form>
<div id="direct_messages" data-room_id="<%= @room.id %>">
<%= render @direct_messages %>
</div>
📝memo
<%= render @direct_messages %>
とは
<% render partial: 'direct_messages/direct_message', collection: @direct_messages %>
の略
この記述をすると、部分テンプレートで繰り返し処理ができる
direct_messageを表示する
<%= direct_message.content %> <br />
### roomチャンネルの作成
speakメソッドを持っているroomチャンネルを作成
```terminal
$ rails g channel room speak
document.addEventListener 'turbolinks:load', ->
App.room = App.cable.subscriptions.create {channel: "RoomChannel", room: $('#direct_messages').data('room_id')},
connected: ->
disconnected: ->
received: (data) ->
$('#direct_messages').append data['direct_message']
speak: (direct_message) ->
@perform 'speak', direct_message: direct_message
$('#chat-input').on 'keypress',(event) ->
if event.ketcode is 13 #enter
App.room.speak event.target.value
event.target.value = ''
event.preventDefault()
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_channel_#{params['room']}"
end
def unsubscribed
end
def speak(data)
DirectMessage.create! message: data['direct_message'],user_id: current_user.id, room_id: params['room']
end
end
jobの作成
$ rails g job DirectMessageBroadcast
job編集
class DirectMessageBroadcastJob < ApplicationJob
queue_as :default
def perform(direct_message)
ActionCable.server.broadcast "room_channel_#{direct_message.room_id}", direct_message: render_direct_message(direct_message)
end
private
def render_direct_message(direct_message)
ApplicationController.renderer.render partial: 'direct_messages/direct_message', locals:{ direct_message: direct_message}
end
end
...
after_create_commit{DirectMessageBroadcastJob.perform_later self}
current_userの情報を取得する
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
verified_user = User.find_by(id: env['warden'].user.id)
return reject_unauthorized_connection unless verified_user
verified_user
end
end
end
### 終わり
誤字、間違いありましたらご連絡いただけばと思います