学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Rails7.1 | 仕事売買アプリ作成 | 44 | メッセージ

↓↓クリックして頂けると励みになります。



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


クライアントからフリーランサーにメッセージを送ってみます。

PCレイアウト
PCレイアウト


モダールフォーム
モダールフォーム



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

PCレイアウト
PCレイアウト



「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

PCレイアウト
PCレイアウト




43 | クレジットカード決済】 << 【ホーム】 >> 【45 | 会話表示




↓↓クリックして頂けると励みになります。