Above is an application that displays a list of tasks. Clicking on the edit link for a task takes us to the edit page for that task. The edit page uses the datetime_select
helper method to render the tasks as a list of drop down lists.
改变5个下拉框并不是更新日期的最好方式。如果在输入框中能填入信息对用户来说是更容易的。应用可以解析输入内容将他们回填到数据库中。
将下拉框改成输入框意味着输入域并没有直接的映射到数据库中。我们不得不为Task模型创建一个虚拟属性,命名为due_at_string。
<h1>Edit Task</h1> <% form_for @task do |form| %> <ol class="formList"> <li> <%= form.label :name, "Name" %> <%= form.text_field :name %> </li> <li> <%= form.label :due_at_string, "Due at" %> <%= form.text_field :due_at_string %> </li> <li> <%= submit_tag "Edit task" %> </li> </ol> <% end %>
在模型中,为虚拟属性添加setter、getter方法,模型中的代码如下:
class Task < ActiveRecord::Base belongs_to :project validates_presence_of :name def due_at_string due_at.to_s(:db) end def due_at_string=(due_at_str) self.due_at = Time.parse(due_at_str) end end
setter方法利用Time的parse方法将输入转化为Time。
有时需要比Time.parse
提供更多功能的函数,可使用Chronic gem,Task模型中添加的代码如下:
require 'chronic'
def due_at_string=(due_at_str) self.due_at = Chronic.parse(due_at_str) end
处理异常
如果传入一个不能解析的字符串,Chronic将返回nil。Time.parse将抛出 ArgumentError
异常 .显然,需向setter中添加rescue。我们将向类中加入一个实例变量,如果存入数据库中时抛出异常,则置为true;添加validate方法,当time不能被解析时,将向task中添加一个error。
def due_at_string=(due_at_str) self.due_at = Time.parse(due_at_str) rescue ArgumentError @due_at_invalid = true end def validate errors.add(:due_at, "is invalid") if @due_at_invalid end
If we try to pass an invalid date now, the error will be caught and added to the model’s list of errors. It’s worth noting that Time.parse
will replace missing or completely invalid parts of the string passed with the equivalent part from Time.now
, so if we pass a completely invalid value like "Hello, world!"
the due date will be set to the current time. An exception will only be raised if an invalid date such as "32-12-2009"
is passed.
We now have a much better way of inputting dates and times into Rails applications. Whether we choose to use the Chronic gem or the built-in time parsing methods we can handle a wide range of date formats from user input.