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

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

【民泊5.1】【MacOSX】予約フォーム

記述更新 app\views\reservations\_form.html.erb
コードをコピーして内容を置き換えてください。

<div class="panel panel-default">
  <div class="panel-heading">
    <span><i class="fa fa-bolt" style="color: #ffb400"></i></span>
    <span class="pull-right">1泊 <%= number_to_currency(@room.price) %></span>
  </div>
  <div class="panel-body">
    <%= form_for([@room, @room.reservations.new]) do |f| %>
      <div class="row">
        <div class="col-md-6">
          <label>チェックイン</label>
          <%= f.text_field :start_date, readonly: true, placeholder: "チェックイン日", class: "form-control datepicker" %>
        </div>
        <div class="col-md-6">
          <label>チェックアウト</label>
          <%= f.text_field :end_date, readonly: true, placeholder: "チェックアウト日", class: "form-control datepicker", disabled: true %>
        </div>
      </div>

      <h4 class="message-alert text-center"><span id="message"></span></h4>
      <div id="preview" style="display: none">
        <table class="reservation-table">
          <tbody>
             <tr>
               <td>宿泊費用</td>
               <td class="text-right", style="white-space: nowrap"><%= number_to_currency(@room.price) %></td>
             </tr>
             <tr>
               <td>宿泊日数</td>
               <td class="text-right"><span id="reservation_nights"></span></td>
             </tr>
             <tr>
               <td class="total">合計金額</td>
               <td class="text-right", style="white-space: nowrap"><span id="reservation_total"></span></td>
             </tr>
           </tbody>
        </table>
      </div>

      <br/>

      <%= f.submit "予約する", id: "btn_book", class: "btn btn-normal btn-block", disabled: true %>
    <% end %>
  </div>
</div>


<script>

  function checkDate(date) {
    dmy = date.getDate() + "-" + (date.getMonth() + 1) + "-" + date.getFullYear();
    return [$.inArray(dmy, unavailableDates) == -1];
  }

  $(function() {

    unavailableDates = [];

    $.ajax({
      url: '<%= preload_room_path(@room) %>',
      dateTyp: 'json',
      success: function(data) {

        $.each(data, function(arrID, arrValue) {
            for(var d = new Date(arrValue.start_date); d <= new Date(arrValue.end_date); d.setDate(d.getDate() + 1)) {
              unavailableDates.push($.datepicker.formatDate('d-m-yy', d));
            }
        });

        $('#reservation_start_date').datepicker({
          dateFormat: 'dd-mm-yy',
          //今日から3ヶ月先まで予約可能
          minDate: 0,
          maxDate: '3m',
          beforeShowDay: checkDate,
          onSelect: function(selected) {
            $('#reservation_end_date').datepicker("option", "minDate", selected);
            $('#reservation_end_date').attr("disabled", false);

            var start_date = $('#reservation_start_date').datepicker('getDate');
            var end_date = $('#reservation_end_date').datepicker('getDate');

            //2日選択すると1泊になる
            var nights = (end_date - start_date)/1000/60/60/24;

            var input = {
              'start_date': start_date,
              'end_date': end_date
            }

            $.ajax({
              url: '<%= preview_room_path(@room) %>',
              data: input,
              success: function(data) {

                if(data.conflict) {
                  $('#message').text("この日付はご利用できません。");
                  $('#preview').hide();
                  $('#btn_book').attr('disabled', true);
                } else {
                  $('#message').text("");
                  $('#preview').show();
                  $('#btn_book').attr('disabled', false);

                  var total = nights * <%= @room.price %>
                  $('#reservation_nights').text(nights);
                  $('#reservation_total').text(total);
                }
              }
            });

          }
        });

        $('#reservation_end_date').datepicker({
          dateFormat: 'dd-mm-yy',
          //今日から3ヶ月先まで予約可能
          minDate: 0,
          maxDate: '3m',
          beforeShowDay: checkDate,
          onSelect: function(selected) {
            $('#reservation_start_date').datepicker("option", "maxDate", selected);

            var start_date = $('#reservation_start_date').datepicker('getDate');
            var end_date = $('#reservation_end_date').datepicker('getDate');

            var nights = (end_date - start_date)/1000/60/60/24;

            var input = {
              'start_date': start_date,
              'end_date': end_date
            }

            $.ajax({
              url: '<%= preview_room_path(@room) %>',
              data: input,
              success: function(data) {

                if(data.conflict) {
                  $('#message').text("この日付ではご予約できません。");
                  $('#preview').hide();
                  $('#btn_book').attr('disabled', true);
                } else {
                  $('#message').text("");
                  $('#preview').show();
                  $('#btn_book').attr('disabled', false);

                  var total = nights * <%= @room.price %>
                  $('#reservation_nights').text(nights);
                  $('#reservation_total').text(total);
                }
              }
            });
          }
        });
      }
    });



  });
</script>



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


1.記述追加 app\controllers\rooms_controller.rb(59行目)

  # 予約 開始日のAJAX
  def preload
    today = Date.today
    reservations = @room.reservations.where("start_date >= ? OR end_date >= ?", today, today)

    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



2.78行目にプライベートメソッド「is_conflict()」を追加します。

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



app\controllers\rooms_controller.rb

class RoomsController < ApplicationController

  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
  end

  def listing
  end

  def pricing
  end

  def description
  end

  def photo_upload
      @photos = @room.photos
  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

  # 予約 開始日のAJAX
  def preload
    today = Date.today
    reservations = @room.reservations.where("start_date >= ? OR end_date >= ?", today, today)
    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 is_conflict(start_date, end_date, room)
    check = room.reservations.where("? < start_date AND end_date < ?", start_date, end_date)
    check.size > 0? true : false
  end

  def set_room
      @room = Room.find(params[:id])
  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 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)
  end

end



記述追加 config\routes.rb
「get 'preload'」の記述追加(18行目)と「get 'preview'」の記述追加(19行目)

Rails.application.routes.draw do

  #ルートをpages#homeに設定
  root 'pages#home'

  get 'pages/home'

  resources :users, only: [:show]

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

  devise_for :users,
  path: '',
  path_names: {sign_in: 'login', sign_out: 'logout', edit: 'profile', sign_up: 'registration'},
  controllers: {registrations: 'registrations'}
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end



ブラウザ確認
ログインしないと予約カレンダーが出ないようになっています。
実際に予約できるか確認してください。

http://localhost:3000/rooms/1


予約確認
予約確認


Posticoで確認します。

予約確認
予約確認