在Rails中单独的date和时间表单字段

我有一个ActiveRecord模型Event与date时间列starts_at 。 我想提出一个表格,其中starts_atdate和时间是分开select的(例如, "23-10-2010"为date, "18:00"为时间)。 这些字段应该由单列starts_at ,并且validation也应该优先针对starts_at

我当然可以使用虚拟属性和钩子,但我想要一个更优雅的解决scheme。 我已经尝试了compos_of ( rdoc )和attribute-decorator( 灯塔讨论 , github )都没有成功。

下面是我想要的粗略轮廓。

 class Event < ActiveRecord::Base validates_presence_of :start_date end # View # On submission this should set start_date. form_for @event do |f| f.text_field :starts_at_date # date-part of start_date f.text_field :starts_at_time_of_day # time-of-day-part of start_date f.submit end 

任何帮助赞赏。

今天看着这个Rails项目,碰到了这个gem:

https://github.com/shekibobo/time_splitter

设置date时间可能是一个困难或丑陋的事情,尤其是通过networkingforms。 find一个好的DatePicker或TimePicker很容易,但让他们在这两个工作都很困难。 TimeSplitter自动生成datetime,time和time属性的date,时间,小时和分钟访问器,使得使用不同的表单input来设置date时间字段的不同部分变得微不足道。

看起来它会为你做的工作

你必须在视图中有一个text_field

据我所知,你可以有一个date_time字段,然后只使用两个不同的input字段来设置字段的不同部分。

 form_for @event do |f| f.date_select :starts_at f.time_select :starts_at, :ignore_date => true f.submit end 

由于导轨date和时间select助手设置了五个不同的参数(年份部分的starts_at(1i) ,月份部分的2i等等),这意味着date_select只设置date部分,而如果您通过:ignore_date => true time_select ,它只会设置小时和分钟部分。

如果你必须有一个text_field我不知道该怎么做,但在发送表单之前设置datetime参数之前,可能会使用一些jQuery魔术。

使用date_selecttime_select是一个好方法。

不过,我想要一个text_field的date(所以我可以使用JavaScriptdateselect器)。

使用strong_parameters或Rails 4+:

车型/ event.rb

 # Add a virtual attribute attr_accessor :start_at_date 

观点/事件/ _form.html.haml

 - # A text field for the date, and time_select for time = f.label :start_at = f.text_field :start_at_date, value: (f.object.start_at.present? ? f.object.start_at.to_date : nil) = f.time_select :start_at, :ignore_date => true 

控制器/ events_controller.rb

 # If using a date_select, time_select, datetime_select # Rails expects multiparameter attributes # Convert the date to the muiltiparameter parts def event_params if !!params[:event] && (params[:event]["start_at(4i)"].present? || params[:event]["start_at(5i)"].present?) if params[:event][:start_at_date].present? start_at_date = params[:event][:start_at_date] else start_at_date = Date.today end year = start_at_date.match(/^(\d{4})[\-\/]/)[1] month = start_at_date.match(/[\-\/](\d{2})[\-\/]/)[1] day = start_at_date.match(/[\-\/](\d{2})$/)[1] params[:event]["start_at(1i)"] = year params[:event]["start_at(2i)"] = month params[:event]["start_at(3i)"] = day end ... 

优雅的解决scheme可能会提供date_time_attribute gem :

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

它将允许您分别设置starts_at_datestarts_at_time

 form_for @event do |f| f.text_field :starts_at_date f.text_field :starts_at_time f.submit end # this will work too: form_for @event do |f| f.date_select :starts_at_date f.time_select :starts_at_time, :ignore_date => true f.text_field :starts_at_time_zone f.submit end # or form_for @event do |f| f.date_select :starts_at_date f.text_field :starts_at_time f.submit end 

它也可以让你玩时区,使用慢性等。

这是因为devise问题吗? 如果您只是将starts_at另存为date时间数据types并使用如下所示,

http://puna.net.nz/timepicker.htm#

它只是运行在你的模型的任何date字段之上。