LoginSignup
2
6

More than 5 years have passed since last update.

Rails 5+ ActionCableで作る! シンプルなチャットアプリ コードのみ コピペ用

Last updated at Posted at 2017-10-25

rails チャットアプリ

コピペ用

リポジトリ
https://github.com/tacyan/camp

rails new camp
cd camp

rails g controller rooms show
config/routes.rb
Rails.application.routes.draw do
  root to: 'rooms#show'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  # Serve websocket cable requests in-process
  # mount ActionCable.server => '/cable'
end
$ rails g model message content:text
$ rails db:migrate
app/controllers/rooms_controller.rb
class RoomsController < ApplicationController
  def show
    @messages = Message.all
  end
end

ディレクトリ作成

mkdir -p app/views/messages
app/views/messages/_message.html.erb
<div class="message">
  <p><%= message.content %></p>
</div>
app/views/rooms/show.html.erb
<h1>Chat room</h1>

<div id="messages">
  <%= render @messages %>
</div>

DBの作成

$ rails console
> Message.create! content: 'Hello world!'
rails g channel room speak
config/routes.rb
Rails.application.routes.draw do
  # (省略)

  # Serve websocket cable requests in-process
  mount ActionCable.server => '/cable'
end
app/assets/javascripts/channels/room.coffee
App.room = App.cable.subscriptions.create "RoomChannel",
  # (省略)

  speak: (message) ->
    @perform 'speak', message: message
app/channels/room_channel.rb
class RoomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "room_channel"
  end

  # (省略)

  def speak(data)
    ActionCable.server.broadcast 'room_channel', message: data['message']
  end
end
app/assets/javascripts/channels/room.coffee
App.room = App.cable.subscriptions.create "RoomChannel",
  # (省略)

  received: (data) ->
    alert data['message']

  # (省略)

ブラウザのJavaScriptコンソールから
App.room.speak('Hello world')

とするとアラートが出力します。

app/views/rooms/show.html.erb
<h1>Chat room</h1>

<div id="messages">
  <%= render @messages %>
</div>

<form>
  <label>Say something:</label><br>
  <input type="text" data-behavior="room_speaker">
</form>
app/assets/javascripts/channels/room.coffee
$(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
  if event.keyCode is 13 # return = send
    App.room.speak event.target.value
    event.target.value = ''
    event.preventDefault()

ここまでは正常に来ましたが、現在はjqueryが入っていない為、
相互通信が出来ません。

Gemfileを変更しましょう。

# add jquery
gem 'jquery-rails'
gem 'jquery-turbolinks'

bundle install

bundle install

$ bundle install|grep jquery
Using jquery-rails 4.3.1
Using jquery-turbolinks 2.1.0
app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks

ここで、Say somethingを叩くと、alertが出力されます。

次にDBに保存しましょう。

app/channels/room_channel.rb
  # (省略)

  def speak(data)
    Message.create! content: data['message']
  end
app/models/message.rb
class Message < ApplicationRecord
  after_create_commit { MessageBroadcastJob.perform_later self }
end

続いて、非同期でブロードキャストするためのMessageBroadcastジョブを作成します。

rails g job MessageBroadcast
app/jobs/message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
  queue_as :default

  def perform(message)
    ActionCable.server.broadcast 'room_channel', message: render_message(message)
  end

  private
    def render_message(message)
      ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message })
    end
end
app/assets/javascripts/channels/room.coffee
App.room = App.cable.subscriptions.create "RoomChannel",
  # (省略)

  received: (data) ->
    $('#messages').append data['message']

  # (省略)
app/views/messages/_message.html.erb
<% cache message do %>
  <div class="message">
    <p><%= message.content %></p>
  </div>
<% end %>
2
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
6