16

I'm using the bootstrap3-datetimepicker-rails gem to let users store the scheduled_date of a WorkOrder in my application (a 'DateTime' property), but I'm getting an argument out of range error when the user submits the form to create the WorkOrder, and the date is very different than what was selected whenever the user pops open the edit screen. The funny thing is that it used to work, but I don't know what code could have changed to break it.

I added the required dependencies & included the proper directives in my CSS/JS files:

gem 'momentjs-rails', '~> 2.5.0'
gem 'bootstrap3-datetimepicker-rails', '~> 3.0.0'

As far as I can tell, my code looks identical to the example on the documentation. Here's the snippet of my form:

  <div class="row">
    <div class="col-md-4">
      <div class="form-group">
        <%= f.label :scheduled_date %>
        <div class='input-group date'>
          <span class="input-group-addon"><span class="fa fa-calendar"></span></span>
          <%= f.text_field :scheduled_date,  class: 'form-control input-lg', id: "service_date_picker" %>
        </div>
      </div>
    </div>
  </div>


  <script type="text/javascript">
      $(function () {
        $('#service_date_picker').datetimepicker({
          icons: {
            time: "fa fa-clock-o",
            date: "fa fa-calendar",
            up: "fa fa-arrow-up",
            down: "fa fa-arrow-down"
          }
        });
      });
  </script>

EDIT (forgot to add controller code - super simple):

work_orders_controller.rb

def create
  @work_order = WorkOrder.new(work_order_params)

  ... [it errors on the line above]
end

And my parameter whitelist:

def work_order_params
  params.require(:work_order).permit(:caller_name, :brief_job_details, :contract_price, :quoted_by, :job_description, :scheduled_date, :time_materials_details, :sheduled_time, :contact_name, :payment_method, :notes, :customer_id, :job_site_id)
end

And an example of the parameters that give the argument out of range error when I save the form:

work_orders_attributes"=>{"0"=>{"caller_name"=>"Justin", "time_materials_details"=>"", "contract_price"=>"", "quoted_by"=>"", "payment_method"=>"", "job_description"=>"", "scheduled_date"=>"05/23/2014 1:28 PM", "notes"=>""}}

Same as my customers_controller.rb where I have a nested form for a WorkOrder inside of the new customer form (everything else on that form works perfectly):

def create
  @customer = Customer.new(customer_params)

  ... [errors above]
end

The date and time saves correctly if it is within 24 hours of now, but even when it saves correctly, the date displays completely weird and unformatted in the text field when I go to edit that WorkOrder. For instance:

When I select the date from the date picker: 05/06/2014 10:28 AM

When I edit the WorkOrder: 2014-06-05 10:28:00.000000

Any ideas? Any preference for whether I should make that field a Date, Time, or DateTime (currently)? Right now, we're working in Central time zone, but that won't always be the case.

Thanks in advance for pointing me in the right direction!

Kyle Carlson
  • 7,967
  • 5
  • 35
  • 43
  • where are you getting the error? in the controller? where is the controller code? – Uri Agassi May 06 '14 at 16:18
  • @UriAgassi: Added controller code as requested. It's not a problem with my strong parameter whitelisting method in my controller either so I didn't include that method. – Kyle Carlson May 06 '14 at 16:28
  • 1
    Please help us help you! If you know the error is in the first line, don't you think the _values_ of `customer_params` and `work_order_params` are relevant – Uri Agassi May 06 '14 at 16:46
  • @UriAgassi Done. I'm not getting any `unpermitted attribute` errors so I didn't think it was a big deal. I'm 99% certain it's something to do with the format either the datepicker is sending or a weird way Ruby is saving the date. Not sure. – Kyle Carlson May 06 '14 at 16:49
  • 1
    Whitelist is not the _values_! Give us a sample value that passes, and a sample value that fails (simply add `p work_order_params` before the first line, and show us the output) – Uri Agassi May 06 '14 at 17:19
  • @UriAgassi Posted as requested. – Kyle Carlson May 06 '14 at 18:31

4 Answers4

12

@Uri Agassi is right: it's the values that you're passing to create the WorkOrder that are the most relevant here.

Try putzing around with the custom date formatting options provided to you by bootstrap-datepicker. If you can get a format that looks good and is easy to parse on the backend, then you'll want to intercept that parameter before it goes to the model for validation.

Regardless of what you'll go with for date formatting on the client-side, you'll still want to parse it into a useable Date or DateTime object server-side in your controller. Check out DateTime#strptime. You can also call #strptime on Date.

Untested, but the idea is there:

def create
  order_params = work_order_params
  order_params[:scheduled_date] = Date.strptime(order_params[:scheduled_date],
                                                '%m/%d/%Y %I:%M %p')
  @work_order = WorkOrder.new(order_params)
end
Ben Kreeger
  • 6,355
  • 2
  • 38
  • 53
  • Oh how I've missed you. That worked perfectly. Thank you so much. I'm just baffled that it used to work without needing any special formatting before going into the db, but whatever. – Kyle Carlson May 06 '14 at 19:19
  • this wont work for me (rails 4.2.0). It wont let me intercept the param and format it before it tries to set it on attribute for some reason. – Sean Jun 19 '15 at 00:57
  • @Sean you can update the params in place before they are passed as a strong param. Check out this stackoverflow: https://stackoverflow.com/questions/19399046/how-to-make-changes-to-strong-parameters-change-to-lowercase – Jason Shultz Jul 21 '15 at 03:27
5

You can remove the modifications from the Controller all together by updating the values in the model. I feel this is a much cleaner (and reusable) approach.

class Work < ActiveRecord::Base

  def scheduled_date=(date)
     begin
       parsed = Date.strptime(date,'%m/%d/%Y %I:%M %p')
       super parsed
     rescue
       date         
     end
  end

end
user1491929
  • 654
  • 8
  • 16
3

It's me helped:
To file application.js writing to end file:

$(function() {
  $('.datepicker').datepicker({format: 'dd-mm-yyyy'});
});
Yuri Malov
  • 1,197
  • 8
  • 11
  • That seems like a much cleaner solution than having to hack my back end code to handle a front-end widget. I'll try that next time! – Kyle Carlson Sep 30 '14 at 16:18
  • 1
    In my case, it was 'dd-mm-yy'. Submits/saves ok. The 4 'y's made it show 20152015 in the form. – JosephK Apr 24 '15 at 14:31
2

This plugin uses moment.js. Basically you need to choose the time format you would like.

example

$(function () {
 $('#datetimepicker').datetimepicker({format: 'MMMM Do YYYY, h:mm'});
});
Benjamin
  • 2,108
  • 2
  • 26
  • 46