ruby on rails多参数属性*如何*工作(datetime_select)

我相信datetime_select是黑魔法。 我真正想弄清楚的是整个1i2i3i4i ……多个参数的东西。 具体如何在后端处理(activerecord,还有其他什么?)。 订单号后面的’i’是什么? 它是一个类型说明符吗? 如果是这样,可用的其他类型是什么? 我已经阅读了date_helper.rb的来源,它非常不透明。

这是我的动机:

我的模型中有一个:datetime列,我希望通过两个text_field输入视图:一个用于日期,一个用于时间。 它们需要经过validation,合并在一起,然后存储到datetime列中。 最终我将使用javascript日历在日期字段中输入日期。

有没有人这样做过? 我尝试使用虚拟属性(除了基本的railscast之外令人难以置信的无记录),问题是当创建一个新的activerecord对象并且具有nil属性时,虚拟属性失败(nil类的未定义方法strftime ,这是有道理的)。

有人有任何建议或最佳做法吗? 谢谢!

我有同样的问题。 这是我发现的……

http://apidock.com/rails/ActiveRecord/Base/assign_multiparameter_attributes

assign_multiparameter_attributes(pairs)private

为需要多个构造函数参数的所有属性类实例化对象。 这是通过使用这些参数在列类型或聚合类型(通过composed_of)对象上调用new来完成的。 因此,将对写为write_on(1)=“2004”,writ_on(2)=“6”,written_on(3)=“24”,将使用Date.new(“2004”,“6”实例化write_on(日期类型) “,”24“)。 您还可以在括号中指定类型转换字符,以便在构造函数中使用之前对参数进行类型转换。 使用i作为Fixnum,使用f作为Float,使用s作为String,使用for作为数组。 如果给定属性的所有值都为空,则该属性将设置为nil。

因此,数字用于列所属的数据类型的参数。 “i”是将其转换为整数。 支持其他类型,如“f”表示浮动等。

您可以在execute_callstack_for_multiparameter_attributes中看到它检测到目标类型并实例化它并传递值。

因此,为了尝试直接回答提出的问题,我认为你不能用它来覆盖DateTime的创建方式,因为它使用的构造函数不支持你要传入的格式。我的解决方法是将DateTime列拆分为一个Date和一个Time列。 用户界面可以按我想要的方式工作。

我想知道是否可以在类上创建属性访问器,分别代表日期和时间,但保留一个DateTime列。 然后表单可以引用那些单独的访问器。 这可能是可行的。 另一种选择可能是使用composed_of进一步自定义类型。

希望能帮助别人。 🙂

这就是我最终想出来的。 如果有人有任何意见,请告诉我。 我很乐意得到反馈。

  validate :datetime_format_and_existence_is_valid before_save :merge_and_set_datetime # virtual attributes for date and time allow strings # representing date and time respectively to be sent # back to the model where they are merged and parsed # into a datetime object in activerecord def date if (self.datetime) then self.datetime.strftime "%Y-%m-%d" else @date ||= (Time.now + 2.days).strftime "%Y-%m-%d" #default end end def date=(date_string) @date = date_string.strip end def time if(self.datetime) then self.datetime.strftime "%l:%M %p" else @time ||= "7:00 PM" #default end end def time=(time_string) @time = time_string.strip end # if parsing of the merged date and time strings is # unsuccessful, add an error to the queue and fail # validation with a message def datetime_format_and_existence_is_valid errors.add(:date, 'must be in YYYY-MM-DD format') unless (@date =~ /\d{4}-\d\d-\d\d/) # check the date's format errors.add(:time, 'must be in HH:MM format') unless # check the time's format (@time =~ /^((0?[1-9]|1[012])(:[0-5]\d){0,2}(\ [AaPp][Mm]))$|^(([01]\d|2[0-3])(:[0-5]\d){0,2})$/) # build the complete date + time string and parse @datetime_str = @date + " " + @time errors.add(:datetime, "doesn't exist") if ((DateTime.parse(@datetime_str) rescue ArgumentError) == ArgumentError) end # callback method takes constituent strings for date and # time, joins them and parses them into a datetime, then # writes this datetime to the object private def merge_and_set_datetime self.datetime = DateTime.parse(@datetime_str) if errors.empty? end