戻る

Rails6.0


民泊サイトの構築 Rails6.0

  (0)
3,000円

タスク5-2   承認予約

このタスクについて


タスクの内容を一部抜粋します。
プロジェクトを購入していただくとこのタスクの内容の全てを読みやすい表示で見ることができます。
プログラムコードが色分けされて見やすくなります。
プログラムコードに行番号が付きます。
本文が色分けされて見やすくなります。
そしてこのアプリケーションのフルコードをダウンロードすることが可能になります。




コマンド
rails g migration AddInstantToRooms instant:bigint


記述追加 db\migrate\20200728030209_add_instant_to_rooms.rb
3行目に「, default: 1」の記述追加
 
class AddInstantToRooms < ActiveRecord::Migration[6.0] 
  def change 
    add_column :rooms, :instant, :bigint, default: 1 
  end 
end 



コマンド
rails g migration AddStatusToReservations status:bigint


記述追加 db\migrate\20200728030757_add_status_to_reservations.rb
3行目に「, default: 0」の記述追加
 class AddStatusToReservations < ActiveRecord::Migration[6.0] 
  def change 
    add_column :reservations, :status, :bigint, default: 0 
  end 
end 



コマンド
rails db:migrate


記述追加 app\models\room.rb(3行目)
   #    instant: {承認制: 0, すぐに予約: 1} 
  enum instant: {Request: 0, Instant: 1} 



app\models\room.rb
 
class Room < ApplicationRecord 

  #    instant: {承認制: 0, すぐに予約: 1} 
  enum instant: {Request: 0, Instant: 1} 

  belongs_to :user 

  has_many :reservations 
  has_many :guest_reviews 
  has_many :reviews 

  has_many_attached :photos 
  has_rich_text :description 

  geocoded_by :address 

  after_validation :geocode, if: :address_changed? 

  validates :home_type, presence: true 
  validates :room_type, presence: true 
  validates :accommodate, presence: true 
  validates :bed_room, presence: true 
  validates :bath_room, presence: true 

  def average_rating 
    guest_reviews.count == 0 ? 0 : guest_reviews.average(:stars).round(2).to_i 
  end  
end 



記述追加 app\models\reservation.rb(3行目)
   #    status: {承認待ち: 0, 承認: 1, 不承認: 2} 
  enum status: {Waiting: 0, Approved: 1, Declined: 2} 



app\models\reservation.rb
 
class Reservation < ApplicationRecord 

  #    status: {承認待ち: 0, 承認: 1, 不承認: 2} 
  enum status: {Waiting: 0, Approved: 1, Declined: 2} 

  belongs_to :user 
  belongs_to :room 

  has_many :reviews 
end 



「app\controllers\rooms_controller.rb」ファイルを編集していきます。


1.75行目を以下の記述に書き換えます。
reservations = @room.reservations.where("(start_date >= ? OR end_date >= ?) AND status = ?", today, today, 1)



2.108行目を以下の記述に書き換えます。
check = room.reservations.where("(? < start_date AND end_date < ?) AND status = ?", start_date, end_date, 1)



3.95行目に「, :instant」の記述追加
params.require(:room).permit(:home_type, :room_type, :accommodate, :bed_room, :bath_room, :listing_name, :summary, :address, :is_tv, :is_kitchen, :is_air, :is_heating, :is_internet, :price, :active, :description, :instant)



記述追加 app\controllers\rooms_controller.rb
 
class RoomsController < ApplicationController 

  protect_from_forgery except: [:upload_photo] 

  before_action :set_room, except: [:index, :new, :create] 
  before_action :authenticate_user!, except: [:show] 
  before_action :is_authorised, only: [:listing, :pricing, :description, :photo_upload, :amenities, :location, :update] 

  def index 
     @rooms = current_user.rooms 
  end 

  def new 
    @room = current_user.rooms.build 
  end 

  def create 
    @room = current_user.rooms.build(room_params) 
    if @room.save 
      redirect_to listing_room_path(@room), notice: "保存しました。" 
    else 
      flash[:alert] = "問題が発生しました。" 
      render :new 
    end 
  end 

  def show 
    @photos = @room.photos 
    @guest_reviews = @room.guest_reviews 
  end 

  def listing 
  end 

  def pricing 
  end 

  def description 
  end 

  def photo_upload 
  end 

  def amenities 
  end 

  def location 
  end 

  def update 
    new_params = room_params 
    new_params = room_params.merge(active: true) if is_ready_room 
    if @room.update(new_params) 
      flash[:notice] = "保存しました。" 
    else 
      flash[:alert] = "問題が発生しました。" 
    end 
    redirect_back(fallback_location: request.referer) 
  end 

  def upload_photo 
    @room.photos.attach(params[:file]) 
    render json: { success: true } 
  end 

  def delete_photo 
    @image = ActiveStorage::Attachment.find(params[:photo_id]) 
    @image.purge 
    redirect_to photo_upload_room_path(@room) 
  end 

  # 予約 開始日のAJAX 
  def preload 
    today = Date.today 
    reservations = @room.reservations.where("(start_date >= ? OR end_date >= ?) AND status = ?", today, today, 1) 
    render json: reservations 
  end 

  # 予約 終了日のAJAX 
  def preview 
    start_date = Date.parse(params[:start_date]) 
    end_date = Date.parse(params[:end_date]) 
    output = { 
      conflict: is_conflict(start_date, end_date, @room) 
    } 
    render json: output 
  end 

  private 
    def set_room 
      @room = Room.find(params[:id]) 
    end 
    
    def room_params 
      params.require(:room).permit(:home_type, :room_type, :accommodate, :bed_room, :bath_room, :listing_name, :summary, :address, :is_tv, :is_kitchen, :is_air, :is_heating, :is_internet, :price, :active, :description, :instant) 
    end 

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

    def is_ready_room 
      !@room.active && !@room.price.blank? && !@room.listing_name.blank? && !@room.photos.blank? && !@room.address.blank? 
    end 

    # 予約 プライベートメソッド 
    def is_conflict(start_date, end_date, room) 
      check = room.reservations.where("(? < start_date AND end_date < ?) AND status = ?", start_date, end_date, 1) 
      check.size > 0? true : false 
    end 
  end 



「app\controllers\reservations_controller.rb」ファイルを編集していきます。


1.3行目に以下の記述を追加します。
before_action :set_reservation, only: [:approve, :decline]



2.22行目の記述「flash[:notice] = "予約が完了しました。"」を以下の記述に書き換えます。
 
        if @reservation.save 
          if room.Request? 
            flash[:notice] = "予約リクエストを送信しました。予約が承認されるまでしばらくお待ち下さい。" 
          else 
            @reservation.Approved! 
            flash[:notice] = "予約が完了しました!ご予約ありがとうございます!" 
          end 
        else 
          flash[:alert] = "ご予約できません!" 
        end 



3.45行目から「approve()」と「decline()」メソッド追加。
 
    def approve 
      @reservation.Approved! 
      redirect_to your_reservations_path 
    end 
  
    def decline 
      @reservation.Declined! 
      redirect_to your_reservations_path 
    end 



4.60行目にプライベートメソッド「set_reservation()」を追加しています。
     def set_reservation 
      @reservation = Reservation.find(params[:id]) 
    end 



app\controllers\reservations_controller.rb
 
class ReservationsController < ApplicationController 

  before_action :authenticate_user! 
  before_action :set_reservation, only: [:approve, :decline] 

  def create 
    room = Room.find(params[:room_id]) 
    if current_user == room.user 
      flash[:alert] = "オーナーが予約することはできません。" 
    else 
        start_date = Date.parse(reservation_params[:start_date]) 
        end_date = Date.parse(reservation_params[:end_date]) 
        days = (end_date - start_date).to_i + 1 
        @reservation = current_user.reservations.build(reservation_params) 
        @reservation.room = room 
        @reservation.price = room.price 
        @reservation.total = room.price * days 
        @reservation.save 
        if @reservation.save 
          if room.Request? 
            flash[:notice] = "予約リクエストを送信しました。予約が承認されるまでしばらくお待ち下さい。" 
          else 
            @reservation.Approved! 
            flash[:notice] = "予約が完了しました!ご予約ありがとうございます!" 
          end 
        else 
          flash[:alert] = "ご予約できません!" 
        end 
      end 
      redirect_to room 
  end 

  def your_trips 
    @trips = current_user.reservations.order(start_date: :asc) 
  end 

  def your_reservations 
    @rooms = current_user.rooms 
  end 

  def approve 
    @reservation.Approved! 
    redirect_to your_reservations_path 
  end 

  def decline 
    @reservation.Declined! 
    redirect_to your_reservations_path 
  end 

  private 
  def reservation_params 
    params.require(:reservation).permit(:start_date, :end_date) 
  end 

  def set_reservation 
    @reservation = Reservation.find(params[:id]) 
  end 
end 
  




書き換え app\controllers\pages_controller.rb(29行目から38行目)
 
        not_available = room.reservations.where( 
          "((? <= start_date AND start_date <= ?) 
          OR (? <= end_date AND end_date <= ?) 
          OR (start_date < ? AND ? < end_date)) 
          AND status = ?", 
          start_date, end_date, 
          start_date, end_date, 
          start_date, end_date, 
          1 
        ).limit(1) 



app\controllers\pages_controller.rb
 
class PagesController < ApplicationController 
  
  def home 
      @rooms = Room.where(active: true).limit(3) 
  end 
  
  def search 
    # ステップ 1 
    if params[:search].present? && params[:search].strip != "" 
      session[:loc_search] = params[:search] 
    end 
    arrResult = Array.new 
    # ステップ 2 
    if session[:loc_search] && session[:loc_search] != "" 
      @rooms_address = Room.where(active: true).near(session[:loc_search], 5, order: 'distance') 
    else 
      @rooms_address = Room.where(active: true).all 
    end 
    # ステップ 3 
    @search = @rooms_address.ransack(params[:q]) 
    @rooms = @search.result 
    @arrRooms = @rooms.to_a 
    # ステップ 4 
    if (params[:start_date] && params[:end_date] && !params[:start_date].empty? &&  !params[:end_date].empty?) 
      start_date = Date.parse(params[:start_date]) 
      end_date = Date.parse(params[:end_date]) 
      @rooms.each do |room| 
        not_available = room.reservations.where( 
          "((? <= start_date AND start_date <= ?) 
          OR (? <= end_date AND end_date <= ?) 
          OR (start_date < ? AND ? < end_date)) 
          AND status = ?", 
          start_date, end_date, 
          start_date, end_date, 
          start_date, end_date, 
          1 
        ).limit(1) 
        if not_available.length > 0 
          @arrRooms.delete(room) 
        end 
      end 
    end 
  end 
end 



記述追加 config\routes.rb(39行目)
   resources :reservations, only: [:approve, :decline] do 
    member do 
      post '/approve' => "reservations#approve" 
      post '/decline' => "reservations#decline" 
    end 
  end 



config\routes.rb
 
Rails.application.routes.draw do 

  # ルートを app\views\pages\home.html.erb に設定 
  root 'pages#home' 

  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, 
              controllers: {registrations: 'registrations'} 

  get 'pages/home' 
  get '/dashboard', to: 'users#dashboard' 
  get '/users/:id', to: 'users#show', as: 'user' 
  get '/your_trips' => 'reservations#your_trips' 
  get '/your_reservations' => 'reservations#your_reservations' 
  get 'search' => 'pages#search' 
  
  post '/users/edit', to: 'users#update' 

  resources :rooms, except: [:edit] do 
    member do 
      get 'listing' 
      get 'pricing' 
      get 'description' 
      get 'photo_upload' 
      get 'amenities' 
      get 'location' 
      get 'preload' 
      get 'preview' 
      delete :delete_photo 
      post :upload_photo 
    end 
    resources :reservations, only: [:create] 
  end 

  resources :guest_reviews, only: [:create, :destroy] 
  resources :host_reviews, only: [:create, :destroy] 

  resources :reservations, only: [:approve, :decline] do 
    member do 
      post '/approve' => "reservations#approve" 
      post '/decline' => "reservations#decline" 
    end 
  end 
  
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html 
end 

記述追加 app\views\rooms\new.html.erb(60行目から70行目)
 
<div class="col-md-6 select"> 
    <div class="form-group"> 
        <label>予約種別</label> 
        <%= f.select :instant, Room.instants.map {|key,value| [key.humanize, key]}, selected: 'Instant', prompt: "選択してください", class: "form-control" %> 
    </div> 
    <label>即時予約制:Instant, 承認予約制:Request</label> 
</div> 
<br/> 
<br/> 
<br/> 
<br/> 



この続きはプロジェクトを購入していただくことで見ることができます。
プロジェクトを購入していただくとこのタスクの内容の全てを読みやすい表示で見ることができます。
プログラムコードが色分けされて見やすくなります。
プログラムコードに行番号が付きます。
本文が色分けされて見やすくなります。
そしてプロジェクトを購入するとこのアプリケーションのフルコードをダウンロードすることができます。

まだレビューはありません。

民泊サイトの構築 Rails6.0

3,000円

Rails6.0で民泊サイトを構築します。
ホストは部屋を登録し、ゲストは宿泊予約できます。
ゲストはクレジットカードで支払いをし、ホストには料金の80%が自動で口座に振り込まれます。
Googleマップによる表示、AJAX検索、日付カレンダーによる予約ができます。
リアルタイムメッセージにより連絡がとれます。
予約確認メールの送信も可能。
写真のアップロード機能、アマゾンS3の利用方法も解説。
レビュー機能の実装方法解説。
フルカレンダー による予約管理。
HEROKUへのデプロイ方法を解説。
フルコードのダウンロード可能。

タスク数: 128