【问题标题】:Rails 4 - Convert datetime into separate date and time fieldsRails 4 - 将日期时间转换为单独的日期和时间字段
【发布时间】:2013-08-29 23:39:38
【问题描述】:

如何将 mysql 日期时间字段转换为两个表单字段 (1) 仅日期,(2) 仅时间,并在表单提交时将两个字段组合回日期时间格式?

这将允许使用以下 gem,但将日期存储在单个日期时间字段中:

gem 'bootstrap-datepicker-rails'
gem 'bootstrap-timepicker-rails'

提前致谢!

【问题讨论】:

    标签: ruby-on-rails datetime datepicker ruby-on-rails-4 timepicker


    【解决方案1】:

    在@Althaf 的帮助下找到了解决方案

    model.rb 添加了虚拟属性 使用before_save 回调转换回日期时间。

    before_save :convert_to_datetime
    
    def sched_date_field
      sched_date.strftime("%d/%m/%Y") if sched_date.present?
    end 
    
    def sched_time_field
      sched_time.strftime("%I:%M%p") if sched_time.present?
    end
    
    def sched_date_field=(date)
      # Change back to datetime friendly format
      @sched_date_field = Date.parse(date).strftime("%Y-%m-%d")
    end
    
    def sched_time_field=(time)
      # Change back to datetime friendly format
      @sched_time_field = Time.parse(time).strftime("%H:%M:%S")
    end
    
    def convert_to_datetime
      self.sched_time = DateTime.parse("#{@sched_date_field} #{@sched_time_field}")
    end
    

    使用 Rails 4,需要将 sched_date_field 和 sched_time_field 添加到 controller.rb

    中的强参数中

    以下是 _form.html.erb

    中的字段
    <%= f.label :sched_date_field, "Scheduled Date" %>
    <%= f.text_field :sched_date_field, :class => "datepicker" %>
    
    <%= f.label :sched_time_field, "Scheduled Time" %>
    <%= f.text_field :sched_time_field, :class => "timepicker" %>
    

    【讨论】:

    • 严格参数是指“强参数”吗?此外,这段代码似乎在 sched_time 上引发了一个未定义的变量错误。
    • 这有点极端,但如果您使用这种技术并要求对sched_time 字段进行任何验证,它将失败。您可以尝试将before_save 更改为before_validation。但同样,如果您有级联验证,这可能会失败。在这个简短的评论中有点难以解释,但相信我,它会失败。
    • @Karl 你推荐什么?我遇到了这个问题。我正在考虑更改我的数据模型以将日期、时间和时区存储为 3 个单独的字段。
    • @Turgs 好吧,已经有一段时间了,但我想我通过在 datepicker 和 timepicker 上使用 javascript 回调将它组合回单个 datetime 并提交它来解决它。
    • 对于那些使用 rails 5 的人 - 好消息是 rails 5 使用虚拟属性为您完成所有类型转换,只需使用属性 API:api.rubyonrails.org/classes/ActiveRecord/Attributes/…
    【解决方案2】:

    你可以使用date_time_attribute gem:

    class MyModel < ActiveRecord::Base
      include DateTimeAttribute
    
      date_time_attribute :scheduled_at
    end
    

    它将允许您分别设置schedule_at_datescheduled_at_time。设置属性后,值将组合成schedule_at

    【讨论】:

      【解决方案3】:

      你可以使用虚拟属性See this Railscast,如果你有专业订阅the revised one

      基本上在视图中你会如下

      <%= f.label :date_field %>
      <%= f.text :date_field %>
      <%= f.label :time_field %>
      <%= f.text :time_field %>
      

      您的数据库仍会保留一个字段,我将称之为 full_date

      现在在您的模型中,您必须按如下方式定义上述 2 个字段。

      def date_field  # What this returns will be what is shown in the field
        full_date.strftime("%m-%d'%y") if full_date.present?
      end 
      
      def time_field
        full_date.strftime("%I:%M%p") if full_date.present?
      end
      
      def time_field=(time)
        full_date = DateTime.parse("#{date_field} #{time_field})
      end
      

      由于您使用的是 Rails 4,因此您必须在强参数中允许 date_field 和 time_field。

      【讨论】:

      • 我认为这就是这样做的方法。我必须在您的解决方案中添加一些内容才能使其正常工作。
      • 您能否提及您所做的更改,以便我可以根据您所做的编辑我的答案,以便其他人以后可以参考
      • 无法确定如何在此回复评论区正确格式化解决方案,因此我在下面发布了解决方案。感谢您的帮助。
      • 太棒了。继续并接受您自己的答案以将此问题设置为已解决。
      【解决方案4】:

      另外,我在控制器中设置了一个解决方案,该解决方案在创建对象之前执行所有日期时间转换,因为更改模型中的数据会影响我的所有测试和验证。 “事件”是我在此处创建的对象,并为其分配了日期时间值。

      #In the controller:
      def convert_to_datetime_and_assign(event, params)
        date_field = Date.parse(params[:date_field]).strftime("%Y-%m-%d")
        start_time_field = Time.parse(params[:start_time_field]).strftime("%H:%M:%S")
        end_time_field = Time.parse(params[:end_time_field]).strftime("%H:%M:%S")
        event.start_time = DateTime.parse("#{date_field} #{start_time_field}")
        event.end_time = DateTime.parse("#{date_field} #{end_time_field}")
        event
      rescue ArgumentError
        event.errors.add(:start_time, :invalid, message: "Date or time was invalid")
        event
      end
      

      在创建和更新控制器方法中我调用了上面的方法:

      @event = convert_to_datetime_and_assign(@event, event_params)
      

      我在表单中添加了 date_field、start_time_field 和 end_time_field 字段,用于创建/更新“事件”。在模型中,我添加了一个访问器来访问这些值。

      attr_accessor :date_field, :start_time_field, :end_time_field
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-15
        • 2020-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多