我有一个ActiveRecord模型Event
,其日期时间列为starts_at
。我想提供一个表单,其中starts_at
的日期和时间是单独选择的(例如"23-10-2010"
表示日期,"18:00"
表示时间。这些字段应该由单个列starts_at
支持,并且验证最好也应该针对starts_at
。
我当然可以使用虚拟属性和钩子,但我想要一个更优雅的解决方案。我已尝试使用composed_of
(rdoc)和属性装饰器(lighthouse discussion,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
任何帮助表示感谢。
答案 0 :(得分:39)
您是否必须在视图中使用text_field
?
据我所知,您可以拥有date_time
字段,然后只使用两个不同的输入字段来设置字段的不同部分。
form_for @event do |f|
f.date_select :starts_at
f.time_select :starts_at, :ignore_date => true
f.submit
end
由于rails日期和时间选择助手设置了五个不同的参数(年份部分为starts_at(1i)
,月份部分为2i
,依此类推),这意味着date_select
仅为日期部分设置它们,而如果您将:ignore_date => true
传递给time_select
,则只会设置小时和分钟部分。
如果你必须有一个text_field
我不知道怎么做,但是在发送表单之前设置datetime参数之前可以使用一些jQuery魔法。
答案 1 :(得分:9)
今天正在关注Rails项目,并遇到了这个宝石:
https://github.com/shekibobo/time_splitter
设置DateTimes可能是一件困难或丑陋的事情,尤其是通过网络表单。找到一个好的DatePicker或TimePicker很容易,但让它们在两者上工作可能很困难。 TimeSplitter会自动为日期时间或时间属性生成日期,时间,小时和分钟的访问器,这使得使用不同的表单输入来设置日期时间字段的不同部分变得微不足道。
看起来它会为你完成这项工作
答案 2 :(得分:3)
使用date_select
和time_select
是一种不错的方式。
但是,我希望日期为text_field
(因此我可以使用JavaScript日期选择器)。
使用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
...
答案 3 :(得分:2)
优雅的解决方案可能会提供date_time_attribute gem:
class MyModel < ActiveRecord::Base
include DateTimeAttribute
date_time_attribute :starts_at
end
它允许您分别设置starts_at_date
和starts_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
它还允许您使用时区,使用慢性等。
答案 4 :(得分:0)
这是因为设计问题吗?如果您将starts_at保存为日期时间数据类型并使用类似:
,则会更容易http://puna.net.nz/timepicker.htm#
它只是在你的模型的任何日期字段之上运行。