ちょっとずつ色々いじれるようになってきたポンコツ大学生エンジニアが助けを経て頑張ってチャット機能を実装してみました🙇
Railsの勉強をはじめて半年ほどですので、理解が至らないことや間違いなどあると思うので指摘していただけるとありがたいです(^^)
チャット機能を作るということは....
まず自分と相手がいないと始まりません!
なので、認証機能を作ってcurrent_user
で今ログインしているuserを得られるとします
また、チャットが始まる、ということは同時にチャットルームもできるということです。なので
$bin/rails g model user
$bin/rails model chat_user
$bin/rails g model chat
$bin/rails g model message
で、まず必要となるモデルを設計します
user、message,chatモデルは当然必要ですが、
chatとuserは多対多の関係であるので、中間テーブルであるchat_user.rb
を作っておきます
で、モデルのアソシエーションは以下のようにしておきます
userは多くのchat,messageを持ち
chatもまた多くのuserを持ち
messageはuserにbelongs_toする。
といったところですね😎
class User < ActiveRecord::Base
has_many :chat_users
has_many :messages
has_many :chats, through: :chat_users
end
class Chat < ActiveRecord::Base
has_many :chat_users
has_many :users, through: :chat_users
has_many :messages
end
class ChatUser < ActiveRecord::Base
belongs_to :chat
belongs_to :user
end
そしてマイグレーションファイルです
lass InitSchema < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :email, null: false
t.string :name, null: false
t.string :password_digest
t.string :remember_digest
end
create_table :chats do |t|
t.integer :service_id, null: false, index: true
t.integer :cny, null: false
t.datetime :start_at#, null: false
t.timestamps null: false
end
create_table :chat_users do |t|
t.integer :user_id, null: false
t.integer :chat_id, null: false
end
create_table :messages do |t|
t.integer :user_id, null: false
t.integer :chat_id, null: false
t.text :contents, null: false
t.date :created_at, null: false
end
## 本来でしたらindexなども貼ったり、いろいろ改善点はありますがいったんこれで最小限のmigrationにしておきます
end
実際にチャット機能を始めるための実装
まずroutingを作ります
Rails.application.routes.draw do
resources :users
resources :chats
end
とりあえず、雑ではありますがチャットできるuserのスコープをuser全体にして誰とででも会話をできるようにします
@users = User.all
ですね
class UsersController < ApplicationController
def index
@users = User.all
@chat = Chat.new
end
end
そしてviewです
楽するため簡単に書きますが、new_chat_pathのparamsとしてそのuserのidを持たせ、
そしてそのidを自動的にheidden_field
を使ってchatのcreateに飛ばします
.container
.row
- @users.each do |user|
%ul
%li= link_to user.name, new_chat_path(reciever_id: user.id)
= form_for @chat, url: chats_path, html: {role: 'form', class:"form-horizontal"} do |f|
= f.hidden_field :reciever_id, value: params[:reciever_id]
.form-group
.col-sm-offset-3
.col-sm-9= f.submit "このサービスで登録", class:"btn btn-primary"
で、このformがcreateで送信されてチャットルームができ、かつそのルームにuserが入ってこなくてはいけないので、chat.rb
に次のメソッドを追加します
class Chat < ActiveRecord::Base
has_many :chat_users
has_many :users, through: :chat_users
has_many :service_categories
has_many :messages
##追加分##
def join(user_id)
self.chat_users.create(user_id: user_id)
end
そしてcreateアクションの中身です😇
class ChatsController < ApplicationController
def create
@chat = Chat.create
@chat.join(current_user.id)
@chat.join(params[:chat][:reciever_id])
redirect_to @chat
end
end
redirectされたchat#showを追加します
def show
@chat = Chat.find(params[:id])
@message = Message.new
@message_logs = @chat.messages#チャットが持つmesaage、すなわちチャットログです
end
そしてここで、userが実際にチャットをするので、Message.newに情報を送信するformが必要です
.container
.row
- @message_logs.each do |message|
%p= message.contents
= form_for @message, url: messages_path, html: {role: 'form', class:"form-horizontal"} do |f|
.form-group
= f.label :contents, class: "col-sm-3 control-label"
.col-sm-9= f.text_area :contents, class: "form-control"
.form-group
= f.hidden_field :chat_id, value: @chat.id
.form-group
.col-sm-4.col-sm-offset-3= f.submit "この内容で送信する", class:"btn btn-primary transition"
そしてこの情報をMessageに格納するためのmessage#createが必要ですね
class MessagesController < ApplicationController
def create
@message = current_user.messages.create(message_params)
redirect_to :back if @message.save
end
private
def message_params
params.require(:message).permit(
:chat_id,
:user_id,
:contents,
:chat_id
)
end
end
最低限のチャット機能の完成です!!😇