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

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

Rails7.1 | 仕事売買アプリ作成 | 35 | 仕事とリクエスト

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



34 | Action】 << 【ホーム】 >> 【36 | raty-js




仕事の確認ページで、それが購入した(購入された)仕事か、それともリクエストによるものかを区別できるように実装します。

モデル



オーダーモデルとリクエストモデルを関連付けします。
コマンド
rails g migration AddRequestToOrder request:references


「db\migrate\20200710001221_add_request_to_order.rb」ファイルを以下のように編集します。


記述更新 db\migrate\20200710001221_add_request_to_order.rb
3行目の記述を「 null: true」に変更しています。

class AddRequestToOrder < ActiveRecord::Migration[7.1]
  def change
    add_reference :orders, :request, null: true, foreign_key: true
  end
end



コマンド マイグレーション適用
rails db:migrate


「app\models\order.rb」ファイルに以下の記述を追加します。


記述追加 app\models\order.rb(3行目)

belongs_to :request, required: false



app\models\order.rb

class Order < ApplicationRecord
  belongs_to :gig, required: false
  belongs_to :request, required: false

  belongs_to :buyer, class_name: "User"
  belongs_to :seller, class_name: "User"

  enum status: [:inprogress, :completed]
end



「app\models\request.rb」ファイルに以下の記述を追加します。


記述追加 app\models\request.rb(6行目)

has_many :orders



app\models\request.rb

class Request < ApplicationRecord
  belongs_to :user
  belongs_to :category

  has_many :offers, dependent: :delete_all
  has_many :orders

  has_one_attached :attachment_file

  validates :title, presence: { message: "空白にはできません" }
  validates :description, presence: { message: "空白にはできません" }
  validates :delivery, numericality: { only_integer: true, message: "数字でなければなりません" }
end


コントローラー



「app\controllers\offers_controller.rb」ファイルを以下のように編集します。


1.記述更新 app\controllers\offers_controller.rb
27行目の「accept()」メソッドの内容を以下のように変更します。

    def accept
        if @offer.pending?
            @offer.accepted!

            if charge(@offer.request, @offer)
                flash[:notice] = "お仕事をお願いしました"
                return redirect_to buying_orders_path
            else
                flash[:alert] = "お願いすることができません"
            end
        end
        redirect_to request.referrer
    end



2.記述追加 app\controllers\offers_controller.rb
50行目に以下の記述を追加します。

    def charge(req, offer)
        order = req.orders.new
        order.due_date = Date.today() + offer.days
        order.title = req.title
        order.seller_name = offer.user.full_name
        order.seller_id = offer.user.id
        order.buyer_name = current_user.full_name
        order.buyer_id = current_user.id
        order.amount = offer.amount
        order.save
    end



app\controllers\offers_controller.rb

class OffersController < ApplicationController
    before_action :authenticate_user!
    before_action :set_offer, only: [:accept, :reject]
    before_action :is_authorised, only: [:accept, :reject]

    def create
        req = Request.find(offer_params[:request_id])

        if req && req.user_id == current_user.id
            redirect_to request.referrer, alert: "自分のリクエストに申し込みはできません。"
        
        elsif Offer.exists?(user_id: current_user.id, request_id: offer_params[:request_id])
            redirect_to request.referrer, alert: "申し込みできるのは1回だけです"
        
        else
            @offer = current_user.offers.build(offer_params)
            if @offer.save
                #redirect_to request.referrer, notice: "保存しました"
                redirect_to my_offers_path, notice: "保存しました"
                
            else
                redirect_to request.referrer, flash: {error: @offer.errors.full_messages.join(', ')}
            end
        end
    end

    def accept
        if @offer.pending?
            @offer.accepted!

            if charge(@offer.request, @offer)
                flash[:notice] = "お仕事をお願いしました"
                return redirect_to buying_orders_path
            else
                flash[:alert] = "お願いすることができません"
            end
        end
        redirect_to request.referrer
    end

    def reject
        if @offer.pending?
            @offer.rejected!
            flash[:notice] = "お断りしました"
        end
        redirect_to request.referrer
    end

    private
    def charge(req, offer)
        order = req.orders.new
        order.due_date = Date.today() + offer.days
        order.title = req.title
        order.seller_name = offer.user.full_name
        order.seller_id = offer.user.id
        order.buyer_name = current_user.full_name
        order.buyer_id = current_user.id
        order.amount = offer.amount
        order.save
    end
    
    def set_offer
        @offer = Offer.find(params[:id])
    end

    def is_authorised
        redirect_to root_path, alert: "権限がありません。" unless current_user.id == @offer.request.user_id
    end

    def offer_params
        params.require(:offer).permit(:amount, :days, :note, :request_id, :status)
    end
end


ビュー



クライアントがオーダー(依頼内容)を確認するためのビューを編集します。
「app\views\orders\buying_orders.html.erb」ファイルの記述を更新します。


記述更新 app\views\orders\buying_orders.html.erb
1. 14行目に以下の記述を追加します。

<% if !o.request.nil? %>
       <div class="badge bg-info mb-4">リクエスト</div>
<% else %>
        <div class="badge bg-dark mb-4">購入済みの仕事</div>
<% end %>  



2.43行目の記述を以下の記述に変更しています。

<%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %>
<%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %>   



app\views\orders\buying_orders.html.erb

<div class="container mt-4">
    <div class="card">
        <div class="card-body">

            <h5 class="card-title text-danger h3 font1">依頼内容(クライアント)</h5>
            <% if @orders.blank? %>
                <h5 class="font1">表示できるオーダーはありません。</h5>
            <% end %>

            <% @orders.each do |o| %>
                <div class="card mt-4">
                    <div class="card-body">

                        <% if !o.request.nil? %>
                            <div class="badge bg-info mb-4">リクエスト</div>
                        <% else %>
                            <div class="badge bg-dark mb-4">購入済みの仕事</div>
                        <% end %>  

                        <div class="mt-2">                                    
                            <% if o.inprogress? %>
                                <span class="font1 alert alert-danger text-center">進行中</span>
                                <%= link_to complete_order_path(o), data: { turbo_method: :put, turbo_confirm: "完了にしてもよろしいですか?" } do %>
                                    <i class="fa fa-thumbs-up fa-lg" style="color: green;"></i><span class="badge bg-success">完了</span>
                                <% end %>
                            <% else %>
                                <span class="font1 alert alert-success text-center">完了</span>
                            <% end %>
                        </div>
                        <ul class="list-group mt-4">

                            <li class="list-group-item" style="border: none;">
                                <span class="font1">依頼日:</span><%= I18n.l(o.created_at, format: :full_date) %>
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">フリーランサー</span>                            
                                <%= link_to user_path(o.seller), class: "tootip", style: "text-decoration: none;" do %>
                                    <span class="btn btn-light"><%= o.seller_name %></span>
                                <% end %>                                                                     
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">仕事名:</span>
                                <%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %>
                                <%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %>   
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">期日:</span>   <%= I18n.l(o.due_date) %>                   
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">価格:</span><%= number_to_currency(o.amount) %>
                            </li>                  
                        </ul>

                    </div>
                </div>
            <% end %>
        </div>
    </div>
</div>



タイトルのリンクをクリックすると、仕事を購入した場合は仕事の詳細ページに、リクエストが成立した場合はリクエストの詳細ページが表示されます。
また、依頼が購入した仕事なのか、リクエストなのかを区別するためのバッジで区別できるようにしました。
ブラウザ確認
http://localhost:3000/buying_orders

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


モバイルレイアウト
モバイルレイアウト



同じように、フリーランサー側の仕事確認ページも修正します。
「app\views\orders\selling_orders.html.erb」ファイルを編集します。


記述変更 app\views\orders\selling_orders.html.erb


1. 15行目に以下の記述を追加します。

<div>
    <% if !o.request.nil? %>
        <div class="badge bg-info mb-4">リクエスト</div>
    <% else %>
        <div class="badge bg-dark mb-4">購入された仕事</div>
    <% end %>
</div>       



2. 42行目の記述を以下の記述に変更しています。

<%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %>
<%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %>   



app\views\orders\selling_orders.html.erb

<div class="container mt-4">
    <div class="card">
        <div class="card-body">

            <h5 class="card-title text-danger h3 font1">オーダー内容(フリーランサー)</h5>
            <% if @orders.blank? %>
                <h5 class="font1">表示できるオーダーはありません。</h5>
            <% end %>

            <% @orders.each do |o| %>
                <div class="card mt-4">
                    <div class="card-body">
                        <div class="mt-2">
                        
                            <div>
                                <% if !o.request.nil? %>
                                    <div class="badge bg-info mb-4">リクエスト</div>
                                <% else %>
                                    <div class="badge bg-dark mb-4">購入された仕事</div>
                                <% end %>
                            </div>                               

                            <% if o.inprogress? %>
                                <span class="font1 alert alert-danger text-center">進行中</span>
                            <% else %>
                                <span class="font1 alert alert-success text-center">完了</span>
                            <% end %>
                        </div>
                        <ul class="list-group mt-4">

                            <li class="list-group-item" style="border: none;">
                                <span class="font1">依頼日:</span><%= I18n.l(o.created_at, format: :full_date) %>
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">クライアント</span>                            
                                <%= link_to user_path(o.buyer), class: "tootip", style: "text-decoration: none;" do %>
                                    <span class="btn btn-light"><%= o.buyer_name %></span>
                                <% end %>                                                                     
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">仕事名:</span>
                                <%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %>
                                <%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %>   
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">期日:</span>   <%= I18n.l(o.due_date) %>                   
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">価格:</span><%= number_to_currency(o.amount) %>
                            </li>                  
                        </ul>

                    </div>
                </div>
            <% end %>
        </div>
    </div>
</div>



ブラウザ確認
http://localhost:3000/selling_orders

フリーランサー依頼確認
フリーランサー依頼確認



34 | Action】 << 【ホーム】 >> 【36 | raty-js





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