简体   繁体   中英

rails invalid date issue

I have a basic reservation form using rails 5.0.1 that is not working, I am getting an ArgumentError (invalid date) error upon submit. The form takes a start and end date and submits to a reservation table for the booking.

The logs show this:

Started GET "/preview?start_date=Wed+May+03+2017+00%3A00%3A00+GMT-0400+(EDT)&end_date=&post_id=3" for ::1 at 2017-04-19 21:47:37 -0400
Processing by ReservationsController#preview as */*
  Parameters: {"start_date"=>"Wed May 03 2017 00:00:00 GMT-0400 (EDT)", "end_date"=>"", "post_id"=>"3"}
  User Load (0.7ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 4 ORDER BY `users`.`id` ASC LIMIT 1
Completed 500 Internal Server Error in 56ms (ActiveRecord: 0.7ms)

ArgumentError (invalid date):

app/controllers/reservations_controller.rb:14:in `parse'
app/controllers/reservations_controller.rb:14:in `preview'

Controller:

class ReservationsController < ApplicationController
    before_action :authenticate_user!, except: [:notify]

    def preload
        post = Post.find(params[:post_id])
        today = Date.today
        reservations = post.reservations.where("start_date >= ? OR end_date >= ?", today, today)
        render json: reservations
    end

    def preview
        start_date = Date.parse(params[:start_date])
        end_date = Date.parse(params[:end_date])

        output = {
            conflict: is_conflict(start_date, end_date)
        }
        render json: output
    end

    def create
      @reservation = current_user.reservations.create(reservation_params)

      if @reservation
        # send request to paypal
          values = {
              business: 'test@test.com',
              cmd: '_xclick',
              upload: 1,
              notify_url: 'http://xyz.ngrok.io/notify',
              amount: @reservation.total,
              item_name: @reservation.post.tool_name,
              item_number: @reservation.id,
              quantity: '1',
              return: 'http://xyz.ngrok.io/your_rentals'
            }
            redirect_to "https://www.sandbox.paypal.com/cgi-bin/webscr?" + values.to_query
        else
            redirect_to @reservation.post, alert: "Oops, something went wrong..."
        end
    end

    def notify
      params.permit!
      status = params[:payment_status]
      reservation = Reservation.find(params[:item_number])
      if status == "Completed"
          reservation.update_attributes status: true
      else
          reservation.destroy
      end
      render nothing: true
    end

    def your_rentals
      @rentals = current_user.reservations
    end

    def your_reservations
      @posts = current_user.posts
    end

private

   def reservation_params
      params.require(:reservation).permit(:start_date, :end_date, :price, :total, :post_id)
   end

       def is_conflict(start_date, end_date)
          post = Post.find(params[:post_id])
          check = post.reservations.where("? < start_date AND end_date < ?", start_date, end_date)
          check.size > 0? true : false
       end
end

View:

<%= form_for([@post, @post.reservations.new]) do |f| %>
  <div class="row">
     <div class="col-md-12 price_tag">
        <span>$<%= @post.price %></span>
        <span class="pull-right">Per Day</span>
     </div>
  </div>
  <div class="row">
    <div class="col-md-6">
       <label>Begin Date</label>
       <%= f.text_field :start_date, readonly: 'true', placeholder: 'Start Date', class: 'form-control' %>
    </div>
    <div class="col-md-6">
       <label>Return Date</label>
       <%= f.text_field :end_date, readonly: 'true', placeholder: 'End Date', class: 'form-control', disabled: true %>
    </div>
  </div>
  <%= f.hidden_field :post_id, value: @post.id %>
  <%= f.hidden_field :price, value: @post.price %>
  <%= f.hidden_field :total, id: 'reservation_total' %>
  <h4><span id="message"></span></h4>
  <div id="preview" style="display: none"> 
     <table class="reservation-table">
       <tbody>
         <tr>
           <td>Day(s)</td>
           <td><span id="reservation_days"></span></td>
         </tr>
         <tr>
           <td>Total</td>
           <td>$<span id="reservation_sum"></span></td>
         </tr>
       </tbody>
     </table><br>
  </div>
  <br>
  <%= f.submit "Book Now", id: "btn_book", class: "btn btn-primary wide", disabled: 'true' %>
<% end %>
<script>
  function unavailable(date) {
    dmy = date.getDate() + "-" + (date.getMonth()+1) + "-" + date.getFullYear();
    return [$.inArray(dmy, unavailableDates) == -1];
   }

  $(function() {
    unavailableDates = [];
    $.ajax({
       url: '/preload',
      data: {'post_id': <%= @post.id %>},
      dataType: '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));
          console.log(d);
      }
    });

      $('#reservation_start_date').datepicker({
        dateFormat: 'dd-mm-yy',
        minDate: 0,
        maxDate: '3m',
        beforeShowDay: unavailable,
        onSelect: function(selected) {
          $('#reservation_end_date').datepicker("option", "minDate", selected);
          $('#reservation_end_date').attr('disabled', false);

          var start_date = $(this).datepicker('getDate');
          var end_date = $('#reservation_end_date').datepicker('getDate');
          var days = (end_date - start_date)/1000/60/60/24 + 1;
            console.log(days)
          var input = {
            'start_date': start_date,
            'end_date': end_date,
            'post_id': <%= @post.id %>
          }

          $.ajax({
            url: "/preview",
            data: input,
            sucess: function(data) {
              if (data.conflict) {
                $('#message').text("This date range is not available.");
                $('#preview').hide();
                $('#btn_book').attr('disabled', true);
                console.log("end date negative");

              } else {

                $('#preview').show();
                $('#btn_book').attr('disabled', false);

                var total = days * <%= @post.price %>
                $('#reservation_days').text(days);
                $('#reservation_sum').text(total);
                $('#reservation_total').val(total);
                console.log(total);
              }
            }
          }); // end ajax

        }
      });

      $('#reservation_end_date').datepicker({
        dateFormat: 'dd-mm-yy',
        minDate: 0,
        maxDate: '3m',
        beforeShowDay: unavailable,
        onSelect: function(selected) {
          $('#reservation_start_date').datepicker("option", "maxDate", selected);

          var start_date = $('#reservation_start_date').datepicker('getDate');
          var end_date = $(this).datepicker('getDate');
          var days = (end_date - start_date)/1000/60/60/24 + 1;
          console.log(days)

          var input = {
            'start_date': start_date,
            'end_date': end_date,
            'post_id': <%= @post.id %>
          }

          $.ajax({
                url: "/preview",
                data: input,
                sucess: function(data) {
                  if (data.conflict) {
                    $('#message').text("This date range is not available.");
                    $('#preview').hide();
                    $('#btn_book').attr('disabled', true);
                  } else {
                    $('#preview').show();
                    $('#btn_book').attr('disabled', false);
                    var total = days * <%= @post.price %>
                    $('#reservation_days').text(days);
                    $('#reservation_sum').text(total);
                    $('#reservation_total').val(total);
                  }
                    }
               }); // end ajax
            } // end onSelect
          }); // end reservation_end_date
      }
    });
  });
 </script>

Model:

class Reservation < ApplicationRecord
  belongs_to :user
  belongs_to :post
end

You are passing a blank date ( "end_date"=>"" ) in your parameters, check on your log:

Parameters: {"start_date"=>"Wed May 03 2017 00:00:00 GMT-0400 (EDT)", "end_date"=>"", "post_id"=>"3"}

So when you do something like end_date = Date.parse(params[:end_date]) you get an error because you are trying to parse an empty string (or, to be more accurate, an invalid_date ; check the docs ).

You need to check first if params[:end_date] contain the right date format (or at least, is not blank) before using Date.parse .

use on your controller

start_date = Date::strptime(reservation_params[:start_date], "%m/%d/%y")
end_date = Date::strptime(reservation_params[:end_date], "%m/%d/%y")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM