↓↓クリックして頂けると励みになります。
【43 | クレジットカード決済】 << 【ホーム】 >> 【45 | 会話表示】
クライアントがフリーランサーにメッセージを送信できるように実装します。
ジェネレータを使ってメッセージモデルを作成していきます。
次のセクションで解説する会話モデルも一緒に作成しておきます。
モデル
まずは会話モデルです。
コマンド
rails g model Conversation sender:references receiver:references
次にメッセージモデルです。
コマンド
rails g model Message content:text user:references conversation:references
「db\migrate\20200728232206_create_conversations.rb」ファイルを編集します。
記述更新 db\migrate\20200728232206_create_conversations.rb
以下のように内容を置き換えて下さい。ユーザーテーブルと関連付けします。
class CreateConversations < ActiveRecord::Migration[7.1] def change create_table :conversations do |t| t.references :sender, foreign_key: { to_table: :users } t.references :receiver, foreign_key: { to_table: :users } t.timestamps end end end
マイグレーションを適用します。
コマンド マイグレーション適用
rails db:migrate
メッセージモデルを編集します。
「app\models\message.rb」ファイルを以下の記述に変更します。
記述追加 app\models\message.rb
5行目に「validates :content, presence: { message: '空白にはできません' }」の記述を追加しています。
class Message < ApplicationRecord belongs_to :user belongs_to :conversation validates :content, presence: { message: '空白にはできません' } end
次に会話モデルを編集します。
「app\models\conversation.rb」ファイルを以下の記述に変更します。
記述変更 app\models\conversation.rb
class Conversation < ApplicationRecord belongs_to :sender, class_name: "User" belongs_to :receiver, class_name: "User" def last_message message = Message.where(conversation_id: self.id).last if message.present? return message else return Message.new updated_at: Time.now end end end
コントローラー
ジェネレーターを使ってメッセージコントローラを作成します。
コマンド
rails g controller messages create
「app\controllers\messages_controller.rb」ファイルを以下のように変更します。
記述変更 app\controllers\messages_controller.rb
class MessagesController < ApplicationController def create if current_user.id == message_params[:receiver_id] redirect_to request.referrer, alert: "自分にメッセージを送ることはできません" end conversation = Conversation.where("(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)", current_user.id, message_params[:receiver_id], message_params[:receiver_id], current_user.id ).first if !conversation.present? conversation = Conversation.create(sender_id: current_user.id, receiver_id: message_params[:receiver_id]) end @message = Message.new(user_id: current_user.id, conversation_id: conversation.id, content: message_params[:content] ) if @message.save redirect_to request.referrer, notice: "メッセージを送りました。" else redirect_to request.referrer, alert: "メッセージを送ることができません。" end end private def message_params params.require(:message).permit(:content, :receiver_id) end end
ルート設定
ルートの設定をします。
3行目に自動で追加された「get 'messages/create'」の記述は削除して下さい。
記述追加 config\routes.rb
26行目に「post 'messages', to: 'messages#create'」の記述を追加しています。
Rails.application.routes.draw do # ルートを app\views\pages\home.html.erb に設定 root 'pages#home' # get get 'pages/home' get '/dashboard', to: 'users#dashboard' get '/users/:id', to: 'users#show', as: 'user' get '/selling_orders', to: 'orders#selling_orders' get '/buying_orders', to: 'orders#buying_orders' get '/all_requests', to: 'requests#list' get '/request_offers/:id', to: 'requests#offers', as: 'request_offers' get '/my_offers', to: 'requests#my_offers' get '/search', to: 'pages#search' get 'settings/payment', to: 'users#payment', as: 'settings_payment' get 'settings/payout', to: 'users#payout', as: 'settings_payout' get '/gigs/:id/checkout/:pricing_type', to: 'gigs#checkout', as: 'checkout' # post post '/users/edit', to: 'users#update' post '/offers', to: 'offers#create' post '/reviews', to: 'reviews#create' post '/search', to: 'pages#search' post '/settings/payment', to: 'users#update_payment', as: "update_payment" post 'messages', to: 'messages#create' # put put '/orders/:id/complete', to: 'orders#complete', as: 'complete_order' put '/offers/:id/accept', to: 'offers#accept', as: 'accept_offer' put '/offers/:id/reject', to: 'offers#reject', as: 'reject_offer' resources :gigs do member do delete :delete_photo post :upload_photo end resources :orders, only: [:create] end resources :requests resources :reviews, only: [:create, :destroy] # device devise_for :users, path: '', path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'} # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. # Can be used by load balancers and uptime monitors to verify that the app is live. get "up" => "rails/health#show", as: :rails_health_check # Defines the root path route ("/") # root "posts#index" end
ビュー
ビューの編集をします。
「app\views\users\show.html.erb」ファイルの23行目に以下の記述を追加します。
<div class="card"> <div class="card-body"> <!-- メッセージ送信ボタン --> <% if current_user.id != @user.id %> <!-- モダールトリガー --> <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#exampleModal"> <div class="font2">メッセージを送る</div> </button> <!-- モダール --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title font2 fs-5" id="exampleModalLabel">メッセージ送信</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= form_with model: Message.new do |f| %> <div class="modal-body"> <div class="container"> <div class="card"> <div class="card-body"> <%= image_tag avatar_url(@user), class: "card-img-top rounded-pill", style: "width: 3rem;" %> <span class="font2"><%= @user.full_name %>へのメッセージ</span> </div> </div> <div class="card mt-2"> <div class="card-body"> <h6 class="font2">確認しましょう</h6> <ul class="list-group"> <li class="list-group-item" style="border: none;">仕事内容</li> <li class="list-group-item" style="border: none;">プラン</li> <li class="list-group-item" style="border: none;">期日</li> <li class="list-group-item" style="border: none;">キャンセルについて</li> </ul> </div> </div> <div class="card mt-2"> <div class="card-body"> <%= f.hidden_field :receiver_id, value: @user.id %> <%= f.text_area :content, class: "w-100", style: "height: 10rem;" %> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <%= f.submit "メッセージを送る", class: "btn btn-outline-primary btn-block" %> </div> <% end %> </div> </div> </div> <% else %> ご自身にメッセージは送れません <% end %> </div> </div>
記述更新 app\views\users\show.html.erb
<div class="container mt-4 mb-4"> <div class="row"> <!-- 左側 --> <div class="col-md-4 mb-4"> <div class="card"> <div class="card-body"> <!-- ステータス --> <div> <% if @user.status %> <span class="badge bg-success"><i class="fa-regular fa-bell"></i>オンライン</span> <% else %> <span class="btn btn-secondary"><i class="fa-regular fa-bell-slash"></i>オフライン</span> <% end %> </div> <!-- アバター --> <%= image_tag avatar_url(@user), class: "img-fluid img-thumbnail rounded-pill" %> <h4 class="text-center"><%= @user.full_name %></h4> <!-- 自己紹介 --> <div class="h5 text-center"><%= @user.about %></div> <div class="card"> <div class="card-body"> <!-- メッセージ送信ボタン --> <% if current_user.id != @user.id %> <!-- モダールトリガー --> <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#exampleModal"> <div class="font2">メッセージを送る</div> </button> <!-- モダール --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title font2 fs-5" id="exampleModalLabel">メッセージ送信</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= form_with model: Message.new do |f| %> <div class="modal-body"> <div class="container"> <div class="card"> <div class="card-body"> <%= image_tag avatar_url(@user), class: "card-img-top rounded-pill", style: "width: 3rem;" %> <span class="font2"><%= @user.full_name %>へのメッセージ</span> </div> </div> <div class="card mt-2"> <div class="card-body"> <h6 class="font2">確認しましょう</h6> <ul class="list-group"> <li class="list-group-item" style="border: none;">仕事内容</li> <li class="list-group-item" style="border: none;">プラン</li> <li class="list-group-item" style="border: none;">期日</li> <li class="list-group-item" style="border: none;">キャンセルについて</li> </ul> </div> </div> <div class="card mt-2"> <div class="card-body"> <%= f.hidden_field :receiver_id, value: @user.id %> <%= f.text_area :content, class: "w-100", style: "height: 10rem;" %> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <%= f.submit "メッセージを送る", class: "btn btn-outline-primary btn-block" %> </div> <% end %> </div> </div> </div> <% else %> ご自身にメッセージは送れません <% end %> </div> </div> </div> </div> </div> <!-- 右側 --> <div class="col-md-8"> <!-- レビュー --> <div class="card mb-2"> <div class="card-body"> <h5 class="card-title font1"><%= @user.full_name %>さんへのレビュー</h5> <%= render "reviews/list" %> </div> </div> <!-- 登録している仕事 --> <div class="card mb-2"> <div class="card-body"> <h5 class="card-title font1"><%= @user.full_name %>さんが登録している仕事</h5> <div class="row"> <% @user.gigs.each do |gig| %> <% if gig.active? %> <div class="col-md-4"> <div class="card mb-2"> <%= link_to gig_path(gig), data: { turbolinks: false} do %> <%= image_tag gig_cover(gig), style: "width: 100%;", class: "card-img-top" %> <% end %> <div class="card-body"> <span class="star-review"><i class="fa fa-star text-warning"></i> <%= gig.average_rating %> <span class="has-text-primary">(<%= gig.reviews.count %>)</span> </span> <%= link_to gig_path(gig), data: { turbolinks: false} do %> <h5 class="card-title"> <span class="btn btn-light"><%= gig.title %></span> </h5> <div class="badge bg-primary"> <% if gig.has_single_pricing%> シングルプランのみ <% else %> 3プラン <% end %> </div> <% end %> </div> </div> </div> <% end %> <% end %> </div> </div> </div> <!-- 登録リクエスト --> <div class="card mt-2"> <div class="card-body"> <h5 class="card-title font1"><%= @user.full_name %>さんが登録しているリクエスト</h5> <div class="row"> <% @user.requests.each do |r| %> <div class="col-md-4"> <div class="card mb-2"> <div class="card-body"> <% if r.offers.count == 0 %> <span class="badge bg-secondary">まだ申し込みはありません</span> <% else %> <span class="badge bg-danger"><%= r.offers.count %>件の申し込みがあります</span> <% end %> <ul class="list-group mt-4"> <li class="list-group-item" style="border: none;"> <span class="font1">リクエスト日:</span><%= I18n.l(r.created_at, format: :full_date) %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">リクエスト名:</span> <%= link_to r.title, request_path(r), class: "btn btn-light" %> </li> <li class="list-group-item" style="border: none;"> <span class="font1">期日:</span> <%= r.delivery %>日 </li> <li class="list-group-item" style="border: none;"> <span class="font1">価格:</span><%= number_to_currency(r.budget) %> </li> <% if r.attachment_file.attached? %> <div class="mt-2"> <%= link_to url_for(r.attachment_file), class: "badge bg-success", download: "Attachment_#{r.attachment_file.id}", style: "text-decoration: none;" do %> <i class="fas fa-paperclip fa-lg p-r-5"></i><span class="fs-6"><%= r.attachment_file.filename %></span> <% end %> </div> <% end %> </ul> </div> </div> </div> <% end %> </div> </div> </div> </div> </div>
ブラウザ確認
http://localhost:3000/users/2
クライアントからフリーランサーにメッセージを送ってみます。
Posticoでメッセージテーブルを確認します。
「app\views\gigs\show.html.erb」ファイルの81行目に以下の記述を追加します。
<div class="card mt-2"> <div class="card-body"> <!-- メッセージ送信ボタン --> <% if current_user.id != @gig.user.id %> <!-- モダールトリガー --> <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#exampleModal"> <div class="font2">メッセージを送る</div> </button> <!-- モダール --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title font2 fs-5" id="exampleModalLabel">メッセージ送信</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= form_with model: Message.new do |f| %> <div class="modal-body"> <div class="container"> <div class="card"> <div class="card-body"> <%= image_tag avatar_url(@gig.user), class: "card-img-top rounded-pill", style: "width: 3rem;" %> <span class="font2"><%= @gig.user.full_name %>へのメッセージ</span> </div> </div> <div class="card mt-2"> <div class="card-body"> <h6 class="font2">確認しましょう</h6> <ul class="list-group"> <li class="list-group-item" style="border: none;">仕事内容</li> <li class="list-group-item" style="border: none;">プラン</li> <li class="list-group-item" style="border: none;">期日</li> <li class="list-group-item" style="border: none;">キャンセルについて</li> </ul> </div> </div> <div class="card mt-2"> <div class="card-body"> <%= f.hidden_field :receiver_id, value: @gig.user.id %> <%= f.text_area :content, class: "w-100", style: "height: 10rem;" %> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <%= f.submit "メッセージを送る", class: "btn btn-outline-primary btn-block" %> </div> <% end %> </div> </div> </div> <% else %> ご自身にメッセージは送れません <% end %> </div> </div>
記述更新 app\views\gigs\show.html.erb
<div class="container"> <div class="mt-4 mb-4"> <%= render 'shared/categories' %> </div> <div class="row"> <!-- 左側 --> <div class="col-md-4"> <% if @gig.has_single_pricing %> <h5 class="font2 bg-light p-2" style="border-radius: 10px;"><%= @gig.title %></h5> <div class="card"> <div class="card-body"> <% @gig.pricings.each do |p| %> <% if p.title %> <div class="card-title font1">シングルプラン <span class="badge bg-danger"><%= number_to_currency(p.price) %></span></div> <div class="font2"><%= p.description %></div> <div><i class="far fa-clock"></i><span class="font2">期日:<%= p.delivery_time %>日</span></div> <div class="mt-4"> <% if (!user_signed_in? && @gig.active) || (user_signed_in? && @gig.active && @gig.user_id != current_user.id) %> <%= form_for([@gig, @gig.orders.new]) do |f| %> <%= hidden_field_tag 'pricing_type', p.pricing_type %> <%= f.submit "仕事を依頼する(#{number_to_currency(p.price)})", class: "btn btn-danger w-100", data: {confirm: "本当によろしいですか?"} %> <% end %> <% else %> <button class="btn btn-danger" disabled>ご利用できません</button> <% end %> </div> <% end %> <% end %> </div> </div> <% else %> <h5 class="font2 bg-light p-2" style="border-radius: 10px;"><%= @gig.title %></h5> <ul class="nav nav-pills mb-3" id="pills-tab" role="tablist"> <% Pricing.pricing_types.each do |key, value| %> <li class="nav-item" role="presentation"> <button class="nav-link <%= 'active' if value == 0 %>" id="pills-<%= key %>-tab" data-bs-toggle="pill" data-bs-target="#pills-<%= key %>" type="button" role="tab" aria-controls="pills-<%= key %>" aria-selected="<%= 'true' if value == 0 %><%= 'false' if !value == 0 %>"> <% if value == 0 %> ベーシック <% elsif value == 1 %> スタンダード <% else %> プレミアム <% end %> </button> </li> <% end %> </ul> <div class="tab-content" id="pills-tabContent"> <% @gig.pricings.each do |p| %> <div class="tab-pane fade <%= 'show active' if p.pricing_type == 'basic' %>" id="pills-<%= p.pricing_type %>" role="tabpanel" aria-labelledby="pills-<%= p.pricing_type %>-tab" tabindex="0"> <div class="card"> <div class="card-body"> <div class="card-title font1"><%= p.title %> <span class="badge bg-danger"><%= number_to_currency(p.price) %></span></div> <div class="font2"><%= p.description %></div> <div><i class="far fa-clock"></i><span class="font2">期日:<%= p.delivery_time %>日</span></div> <div class="mt-4"> <% if (!user_signed_in? && @gig.active) || (user_signed_in? && @gig.active && @gig.user_id != current_user.id) %> <%= link_to "仕事を依頼する (#{number_to_currency(p.price)})", checkout_path(id: @gig.id, pricing_type: p.pricing_type), class: "btn btn-danger w-100" %> <% else %> <button class="btn btn-danger" disabled>依頼できません</button> <% end %> </div> </div> </div> </div> <% end %> </div> <% end %> <div class="card mt-2"> <div class="card-body"> <!-- メッセージ送信ボタン --> <% if current_user.id != @gig.user.id %> <!-- モダールトリガー --> <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#exampleModal"> <div class="font2">メッセージを送る</div> </button> <!-- モダール --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title font2 fs-5" id="exampleModalLabel">メッセージ送信</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= form_with model: Message.new do |f| %> <div class="modal-body"> <div class="container"> <div class="card"> <div class="card-body"> <%= image_tag avatar_url(@gig.user), class: "card-img-top rounded-pill", style: "width: 3rem;" %> <span class="font2"><%= @gig.user.full_name %>へのメッセージ</span> </div> </div> <div class="card mt-2"> <div class="card-body"> <h6 class="font2">確認しましょう</h6> <ul class="list-group"> <li class="list-group-item" style="border: none;">仕事内容</li> <li class="list-group-item" style="border: none;">プラン</li> <li class="list-group-item" style="border: none;">期日</li> <li class="list-group-item" style="border: none;">キャンセルについて</li> </ul> </div> </div> <div class="card mt-2"> <div class="card-body"> <%= f.hidden_field :receiver_id, value: @gig.user.id %> <%= f.text_area :content, class: "w-100", style: "height: 10rem;" %> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <%= f.submit "メッセージを送る", class: "btn btn-outline-primary btn-block" %> </div> <% end %> </div> </div> </div> <% else %> ご自身にメッセージは送れません <% end %> </div> </div> </div> <!--右側 --> <div class="col-md-8"> <div class="card mt-4 mb-4"> <div class="card-body"> <h5 class="font1">フリーランサー</h5> <div class="mt-2"> <%= link_to user_path(@gig.user), style: "text-decoration:none;" do %> <%= image_tag avatar_url(@gig.user), class: "bd-placeholder-img figure-img img-fluid rounded-pill", style: "width: 80px;" %> <span class="font2 text-dark h4"><%= @gig.user.full_name %></span> <% end %> </div> <div class="font2"> <%= @gig.description %> </div> </div> </div> <!-- カルーセル表示 --> <div class="card"> <div class="card-body"> <div id="carouselExampleIndicators" class="carousel slide" data-bs-ride="carousel"> <div class="carousel-indicators"> <% @photos.each do |photo| %> <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="<%= @i %>" class="<%= 'active' if photo.id == @photos[0].id %>" aria-current="true" aria-label="Slide <%= @i+1 %>"></button> <% @i = @i +1 %> <% end %> </div> <div class="carousel-inner"> <% @gig.photos.each do |photo| %> <div class="carousel-item <%= 'active' if photo.id == @photos[0].id %>"> <%= image_tag url_for(photo), class: "d-block w-100", style: "border-radius: 10px;" %> </div> <% end %> </div> <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="visually-hidden">Previous</span> </button> <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="visually-hidden">Next</span> </button> </div> </div> </div> <!-- Youtube表示 --> <% if @gig.video.present? %> <div class="card mt-4"> <iframe height="360" src="https://www.youtube.com/embed/<%= @gig.video %>" allowfullscreen></iframe> </div> <% end %> </div> </div> </div>
ブラウザを確認します。
動作を確認して下さい。
http://localhost:3000/gigs/10
「app\views\requests\show.html.erb」ファイルの29行目に以下の記述を追加します。
<div class="card"> <div class="card-body"> <!-- メッセージ送信ボタン --> <% if current_user.id != @request.user.id %> <!-- モダールトリガー --> <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#exampleModal"> <div class="font2">メッセージを送る</div> </button> <!-- モダール --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title font2 fs-5" id="exampleModalLabel">メッセージ送信</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= form_with model: Message.new do |f| %> <div class="modal-body"> <div class="container"> <div class="card"> <div class="card-body"> <%= image_tag avatar_url(@request.user), class: "card-img-top rounded-pill", style: "width: 3rem;" %> <span class="font2"><%= @request.user.full_name %>へのメッセージ</span> </div> </div> <div class="card mt-2"> <div class="card-body"> <h6 class="font2">確認しましょう</h6> <ul class="list-group"> <li class="list-group-item" style="border: none;">仕事内容</li> <li class="list-group-item" style="border: none;">プラン</li> <li class="list-group-item" style="border: none;">期日</li> <li class="list-group-item" style="border: none;">キャンセルについて</li> </ul> </div> </div> <div class="card mt-2"> <div class="card-body"> <%= f.hidden_field :receiver_id, value: @request.user.id %> <%= f.text_area :content, class: "w-100", style: "height: 10rem;" %> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <%= f.submit "メッセージを送る", class: "btn btn-outline-primary btn-block" %> </div> <% end %> </div> </div> </div> <% else %> ご自身にメッセージは送れません <% end %> </div> </div>
記述更新 app\views\requests\show.html.erb
<div class="container mt-4"> <div class="row"> <!-- 左側 --> <div class="col-md-4"> <div class="card mb-2"> <div class="card-body"> <h5 class="card-title font1">リクエストに申し込む</h5> <%= form_for Offer.new do |f| %> <%= f.hidden_field :request_id, value: @request.id %> <div class="mt-4"> <label for="" class="label">希望価格 (円)</label> <%= f.text_field :amount, class: "form-control" %> </div> <div class="mt-2"> <label for="" class="label">期日 (日)</label> <%= f.text_field :days, class: "form-control" %> </div> <div class="mt-2"> <label for="" class="label">コメント</label> <%= f.text_area :note, class: "form-control" %> </div> <div class="mt-4"> <%= f.submit '申し込む', class: "btn btn-danger w-100" %> </div> <% end %> </div> </div> <div class="card"> <div class="card-body"> <!-- メッセージ送信ボタン --> <% if current_user.id != @request.user.id %> <!-- モダールトリガー --> <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#exampleModal"> <div class="font2">メッセージを送る</div> </button> <!-- モダール --> <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title font2 fs-5" id="exampleModalLabel">メッセージ送信</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= form_with model: Message.new do |f| %> <div class="modal-body"> <div class="container"> <div class="card"> <div class="card-body"> <%= image_tag avatar_url(@request.user), class: "card-img-top rounded-pill", style: "width: 3rem;" %> <span class="font2"><%= @request.user.full_name %>へのメッセージ</span> </div> </div> <div class="card mt-2"> <div class="card-body"> <h6 class="font2">確認しましょう</h6> <ul class="list-group"> <li class="list-group-item" style="border: none;">仕事内容</li> <li class="list-group-item" style="border: none;">プラン</li> <li class="list-group-item" style="border: none;">期日</li> <li class="list-group-item" style="border: none;">キャンセルについて</li> </ul> </div> </div> <div class="card mt-2"> <div class="card-body"> <%= f.hidden_field :receiver_id, value: @request.user.id %> <%= f.text_area :content, class: "w-100", style: "height: 10rem;" %> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <%= f.submit "メッセージを送る", class: "btn btn-outline-primary btn-block" %> </div> <% end %> </div> </div> </div> <% else %> ご自身にメッセージは送れません <% end %> </div> </div> </div> <!-- 右側 --> <div class="col-md-8"> <div class="card"> <div class="card-body"> <!-- タイトル --> <div class="card-title"> <h3 class="font1"><%= @request.title %></h3> <div class="mt-4"> <div class="mt-4"> <span class="font1">期日:</span><%= @request.delivery %>日 | <span class="font1">申し込み:</span><%= @request.offers.count %>件 | <span class="font1">予算:</span> <%= number_to_currency(@request.budget) %> </div> </div> <!-- 内容 --> <div class="card"> <div class="card-body"> <div> <span class="font1">カテゴリー:</span><%= @request.category.name %> </div> <div> <span class="font1">リクエスト日:</span><%= I18n.l(@request.created_at, format: :full_date) %> </div> <h6 class="font1 mt-4">クライアント</h6> <div class="mt-2"> <%= link_to user_path(@request.user), style: "text-decoration:none;" do %> <%= image_tag avatar_url(@request.user), class: "bd-placeholder-img figure-img img-fluid rounded-pill", style: "width: 80px;" %> <span class="font2 text-dark h4"><%= @request.user.full_name %></span> <% end %> </div> <div class="card-title mt-4"><h4 class="font1">内容</strong></h4> <div class="mt-4"> <span class="font2"><%= @request.description %></span> </div> <% if @request.attachment_file.attached? %> <div class="mt-4 mb-4"> <%= link_to url_for(@request.attachment_file), class: "badge bg-success", download: "Attachment_#{@request.attachment_file.id}", style: "text-decoration: none;" do %> <i class="fas fa-paperclip fa-lg p-r-5"></i><span class="fs-6"><%= @request.attachment_file.filename %></span> <% end %> </div> <% end %> </div> </div> </div> </div> </div> </div> </div> </div>
ブラウザを確認します。
動作を確認してください。
http://localhost:3000/requests/5
【43 | クレジットカード決済】 << 【ホーム】 >> 【45 | 会話表示】
↓↓クリックして頂けると励みになります。