#目標
ユーザー間でDMを送り合えるようになる!!
#イメージ
UserがいろんなUserとDMをできると考えます。
ここでは4つのモデルを通して、DMを実装します!
Userモデル: User情報
Roomモデル: 今回はチャットルームに2人のUserが入るイメージです
Entryモデル: どのUserがどのRoomに所属しているか
Messageモデル: UserがどのRoomでどんなMessageを送ったか
#いざ実装
##プロジェクトの作成
$ rails new dm_sample
##Userモデルの作成
今回はdeviseを使用して、ログインできるようにします。
Gemfileに以下を追加してください
gem 'devise'
gemを追加したので以下のコマンドを実行しましょう。
$ bundle install
Railsプロジェクトにdeviseをインストールします
$ rails g devise:install
ここからdeviseを使ってUserモデルを作成していきます。
$ rails g devise:controllers users
$ rails g devise user name:string
$ rails g devise:views
$ rails db:migrate
##他のモデルの作成
次にRoomモデル、 Entryモデル、Messageモデルを作成します。
$ rails g model room name:string
$ rails g model entry user:references room:references
$ rails g model message user:references room:references content:text
$ rails db:migrate
##アソシエーション
1対多の関係が複数発生したのでアソシエーション(モデル同士の結びつけ)を行います。
app/modelsの中の次のファイルを以下のように書き換えてください。
####user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :messages, dependent: :destroy
has_many :entries, dependent: :destroy
end
####entry.rb
class Entry < ApplicationRecord
belongs_to :user
belongs_to :room
end
####room.rb
class Room < ApplicationRecord
has_many :messages, dependent: :destroy
has_many :entries, dependent: :destroy
end
####message.rb
class Message < ApplicationRecord
belongs_to :user
belongs_to :room
end
##コントローラーの作成
$ rails g controller users index show
$ rails g controller rooms
$ rails g controller messages
class UsersController < ApplicationController
before_action :authenticate_user!, :only => [:show]
def index
@users=User.all
end
def show
@user=User.find(params[:id])
@currentUserEntry=Entry.where(user_id: current_user.id)
@userEntry=Entry.where(user_id: @user.id)
if @user.id == current_user.id
else
@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
if @isRoom
else
@room = Room.new
@entry = Entry.new
end
end
end
end
class RoomsController < ApplicationController
before_action :authenticate_user!
def create
@room = Room.create
@entry1 = Entry.create(:room_id => @room.id, :user_id => current_user.id)
@entry2 = Entry.create(params.require(:entry).permit(:user_id, :room_id).merge(:room_id => @room.id))
redirect_to "/rooms/#{@room.id}"
end
def show
@room = Room.find(params[:id])
if Entry.where(:user_id => current_user.id, :room_id => @room.id).present?
@messages = @room.messages
@message = Message.new
@entries = @room.entries
else
redirect_back(fallback_location: root_path)
end
end
end
class MessagesController < ApplicationController
before_action :authenticate_user!, :only => [:create]
def create
if Entry.where(:user_id => current_user.id, :room_id => params[:message][:room_id]).present?
@message = Message.create(params.require(:message).permit(:user_id, :content, :room_id).merge(:user_id => current_user.id))
redirect_to "/rooms/#{@message.room_id}"
else
redirect_back(fallback_location: root_path)
end
end
end
##ルーティングの作成
Rails.application.routes.draw do
devise_for :users
resources :users, :only => [:index, :show]
root "users#index"
resources :messages, :only => [:create]
resources :rooms, :only => [:create, :show, :index]
end
##ビューの作成
<h1>DMサンプルアプリ</h1>
<% if user_signed_in? %>
<h2>Hello <%= current_user.email %></h2>
<% @users.each do |u| %>
<p><a href="/users/<%= u.id %>"><%= u.email %>さん</a></p>
<hr>
<% end %>
<%= link_to "ログアウト", destroy_user_session_path, :method => :delete %>
<% else %>
<%= link_to "ユーザーを登録する", new_user_registration_path %>
<br>
<%= link_to "ログインする", new_user_session_path %>
<% end %>
<h1>ユーザー詳細</h1>
<h2><%= @user.email %></h2>
<% if @user.id == current_user.id %>
<% else %>
<% if @isRoom == true %>
<p><a href="/rooms/<%= @roomId %>">チャットへ</a>
<% 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 %>
<%= link_to "ユーザー一覧に戻る", users_path %>
<h1>DM</h1>
<h4>参加者</h4>
<% @entries.each do |e| %>
<h5><strong><a href="/users/<%= e.user.id %>"><%= e.user.email%>さん</a></strong></h5>
<% end %>
<hr>
<% if @messages.present? %>
<% @messages.each do |m| %>
<strong><%= m.content %></strong>
<small>by <strong><a href="/users/<%= m.user_id %>"><%= m.user.email %>さん</a></strong></small>
<hr>
<% end %>
<% else %>
<h3 class="text-center">メッセージはまだありません</h3>
<% end %>
<%= form_for @message do |f| %>
<%= f.text_field :content, :placeholder => "メッセージを入力して下さい" , :size => 70 %>
<%= f.hidden_field :room_id, :value => @room.id %>
<br>
<%= f.submit "投稿する" %>
<% end %>
<%= link_to "ユーザー一覧に戻る", users_path %>
#完成
これでユーザー同士のDM機能が完成しました。viewにcssを全く加えていないのでかなり簡素なものとなっています。