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

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

Rails6.0 | 仕事売買サイトの構築 | 31 | 仕事完了

[30]仕事を受ける << [ホームに戻る] >> [32]レビュー


申込みを受けたお仕事が完了したとき、決済ページに移動できるようにします。


コマンド
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[6.0]
  def change
    add_reference :orders, :request, null: true, foreign_key: true
  end
end



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


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


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

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(7行目)

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
51行目に以下の記述を追加します。

    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
26行目の記述を変更しています。

<td>
    <%= link_to o.title, gig_path(o.gig) if !o.gig.nil? %>
    <%= link_to o.title, request_path(o.request) if !o.request.nil? %>                        
</td>



app\views\orders\buying_orders.html.erb
コードをコピーしてファイルの内容を置き換えて下さい。

<section class="section">
    <div class="container">
        <p class="title">買った注文の確認</p>
        <table class="table is-fullwidth">
            <thead>
                <tr>
                    <th>注文日</th>
                    <th>売り主</th>
                    <th>タイトル</th>
                    <th>期日</th>
                    <th>価格</th>
                    <th>ステータス</th>
                    <th>アクション</th>
                </tr>
            </thead>
            <tbody>
                <% if @orders.blank? %>
                  <tr>
                      <td colspan="7" class="has-text-centered"><h1>表示できる注文がありません。</h1></td>
                  </tr>
                <% end %>
                <% @orders.each do |o| %>
                    <tr>
                        <td><%= I18n.l(o.created_at, format: :full_date) %></td>
                        <td><%= o.seller_name %></td>
                        <td>
                            <%= link_to o.title, gig_path(o.gig) if !o.gig.nil? %>
                            <%= link_to o.title, request_path(o.request) if !o.request.nil? %>                        
                        </td>
                        <td><%= I18n.l(o.due_date) %></td>
                        <td><%= number_to_currency(o.amount) %></td>
                        <td>
                            <span class="tag <%= 'is-warning' if o.inprogress? %> <%= 'is-success' if o.completed? %>">
                                <% if o.inprogress? %>
                                    進行中
                                <% else %>
                                    お仕事完了
                                <% end %>
                            </span>
                        </td>
                        <td>
                            <%= link_to 'お仕事完了にする', complete_order_path(o), method: :put, class: "button is-small is-primary #{'is-hidden' if o.completed?}" %>
                        </td>
                    </tr>
                <% end %>
            </tbody>
        </table>
    </div>
</section>



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


ステータスがまだ「進行中」の場合、タイトルのリンクをクリックするとリクエストの詳細ページが表示されます。

ステータス「進行中」
ステータス「進行中」

リクエストの詳細ページが表示される
リクエストの詳細ページが表示される



ステータスを「お仕事完了」にした後にタイトルのリンクをクリックすると、決済できるお仕事の詳細ページが表示されます。

ステータス「お仕事完了」
ステータス「お仕事完了」


決済のページに移動
決済のページに移動



今回の変更により、「app\views\orders\selling_orders.html.erb」ファイルの記述も変更しなければなりません。


記述変更 app\views\orders\selling_orders.html.erb(25行目)
25行目の記述を変更しています。

<td>
    <%= link_to o.title, gig_path(o.gig) if !o.gig.nil? %>
    <%= link_to o.title, request_path(o.request) if !o.request.nil? %>
</td>



app\views\orders\selling_orders.html.erb

<section class="section">
    <div class="container">
        <p class="title">売った注文の確認</p>
        <table class="table is-fullwidth">
            <thead>
                <tr>
                    <th>注文日</th>
                    <th>買い主</th>
                    <th>タイトル</th>
                    <th>期日</th>
                    <th>価格</th>
                    <th>ステータス</th>
                </tr>
            </thead>
            <tbody>
                <% if @orders.blank? %>
                  <tr>
                      <td colspan="6" class="has-text-centered"><h1>表示できる発注はありません。</h1></td>
                  </tr>
                <% end %>
                <% @orders.each do |o| %>
                    <tr>
                        <td><%= I18n.l(o.created_at, format: :full_date) %></td>
                        <td><%= o.buyer_name %></td>
                        <td>
                            <%= link_to o.title, gig_path(o.gig) if !o.gig.nil? %>
                            <%= link_to o.title, request_path(o.request) if !o.request.nil? %>
                        </td>
                        <td><%= I18n.l(o.due_date) %></td>
                        <td><%= number_to_currency(o.amount) %></td>
                        <td>
                            <span class="tag <%= 'is-warning' if o.inprogress? %> <%= 'is-success' if o.completed? %>">
                                <% if o.inprogress? %>
                                    進行中
                                <% else %>
                                    お仕事完了
                                <% end %>
                            </span>
                        </td>
                    </tr>
                <% end %>
            </tbody>
        </table>
    </div>
</section>



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


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


[30]仕事を受ける << [ホームに戻る] >> [32]レビュー