How do I change the format ActiveRecord expects when parsing dates from a text field in a form?

前端 未结 5 1676
孤独总比滥情好
孤独总比滥情好 2021-01-04 02:37

The problem

  1. I have a Ruby on Rails model with a Date attribute.
  2. In the form for this model, I am using a single text field with a JQuery datepicker
相关标签:
5条回答
  • 2021-01-04 02:43

    Since you don't want to change the picker's format, I would suggest you use a hidden field for the actual model property.

    For example, add a hidden field for the model's date property, assuming you use a form builder as usual:

    f.hidden_field :date

    Then for the picker text input, don't bind it to the model's date property. Let's say the hidden field has ID 'modelname_date' and the picker text input has ID 'date_picker', use the following to make it work:

    $(function(){
      $("#date_picker").datepicker({altField: '#nodelname_date', altFormat: 'dd/mm/yyyy'});
    });
    

    In this way the date picker shows the date as 'mm/dd/yyyy' but Rails will see the date as 'dd/mm/yyyy'.

    Update:

    If you want to work this out on the Rails side, here's another solution I'd suggest:

    • Add a virtual property to your model: attr_accessor :bad_format_date
    • Add a before_validation callback in which you parse the input date and assign it to the real field:
    before_validation do
      self.date = Date.strptime(bad_format_date, "%m/%d/%Y")
    end
    

    Then for the form on the view use bad_format_date but initialize it with the date field value (if it's an edit form).

    0 讨论(0)
  • 2021-01-04 02:52

    I just add the following monkey patch to config/time_formats.rb

    class Date
      class << self
        alias :euro_parse :_parse
        def _parse(str,comp=false)
          str = str.to_s.strip
          if str == ''
            {}
          elsif str =~ /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{2,4})/
            year,month,day = $3.to_i,$1,$2
            date,*rest = str.split(' ')
            year += (year < 35 ? 2000 : 1900) if year < 100
            euro_parse("#{year}-#{month}-#{day} #{rest.join(' ')}",comp)
          else
            euro_parse(str,comp)
          end  
        end
      end
    end
    
    0 讨论(0)
  • 2021-01-04 02:58

    You could try do something like this.

    $(function(){
     $('#date_picker').datepicker( {
          beforeShowDay: $.datepicker.noWeekends, 
          showOtherMonths: true,
          selectOtherMonths: true,
          dateFormat: 'dd-mm-yy',
          defaultDate: date,
          gotoCurrent: true
    
    }); 
    
    0 讨论(0)
  • 2021-01-04 03:01

    The timeliness gem makes ruby date/time parsing much more customizeable and integrates well with Rails.

    Since you're working with Rails, be sure to check out the validates_timeliness project as well by the same guy. It includes all of timeliness plus sophisticated date/time validation methods for ActiveModel.

    0 讨论(0)
  • 2021-01-04 03:08

    I initially thought this could be solved through the Rails internationalization features, but it turns out I was wrong.

    Ever since Ruby 1.9, the standard format for date parsing is dd/mm/yyyy, so as to better accomodate international users. More details can be found in this SO answer.

    That standard is maintained in Rails, as Date.parse is now used to process data from form inputs. Using a before_validation callback won't work because the field is going to be received as nil by the callback method.

    Right now there are two gems dealing with this specific issue, namely that date parsing in Rails does not follow the locale settings from I18n.locale. Both seem to work well.

    1. delocalize, by clemens - Seems to have been applied successfully in a decent number or projects and has the highest number of stars at the moment.

    2. i18n_alchemy by carlosantoniodasilva - This one has been released more recently. The author is a Rails core team member, and a very active one at that. Definitely deserves a look.

    0 讨论(0)
提交回复
热议问题