Rails的date格式在text_field

我有一个在text_field中显示date的导轨forms:

<%= form.text_field :check_in_date %> 

date呈现为yyyy-mm-dd

我想弄清楚如何让它显示为mm-dd-yyyy

我试图添加这个configuration,但它没有工作。

 ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!( :default => '%m/%d/%Y' ) 

简单的一次性解决scheme是在text_field调用中使用:value选项,而不是将某些内容添加到ActiveRecord::BaseCoreExtensions

例如:

 <%= f.text_field :some_date, :value => @model_instance.some_date.strftime("%d-%m-%Y") %> 

我将这些添加到我的initializers/time_formats.rb ,它工作得很好:

 # Default format for displaying dates and times Date::DATE_FORMATS[:default] = "%m/%d/%Y" Time::DATE_FORMATS[:default] = "%m/%d/%Y" 

使用Ruby 1.9.3和Rails 3.2.x

我花了一些时间在代码中查看,并且更改DATE_FORMAT将不起作用,因为Rails从不要求date格式。 菲利克斯的设定:价值的解决scheme确实奏效,但感觉麻烦:为什么我必须手动设置date特定的文本域的值? 所以这是一个代码,我想要更好的东西。

这是我的简短解决scheme,但是我会稍微解释一下,因为我希望别人会写更好的东西:

 MyModel < ActiveRecord::Base # ... self.columns.each do |column| if column.type == :date define_method "#{column.name}_before_type_cast" do self.send(column.name).to_s end end end end 

有些更长的解释:当一个文本字段设置值属性,它将首先查看选项散列(这就是为什么费利克斯的解决scheme),但如果它不在那里,它会调用form.object.check_in_date_before_type_cast ,这(后一些method_missing魔术)会调用form.object.attributes_before_type_cast['check_in_date'] ,它将在form.object中的@attributes哈希中查找'check_in_date'。 我的猜测是@attributes散列在被包装在一个Ruby对象中之前获得了直接的MySQLstring表示(它遵循'yyyy-mm-dd'格式),这就是为什么简单地设置DATE_FORMAT本身不工作。 因此,上面的dynamic方法创build为所有实际执行types转换的date对象创build方法,允许您使用ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS[:default]来格式化date。

这感觉有点肮脏,因为'_before_type_cast'的整个目的是为了避免一个types转换,而这是“thar be dragon”monkeypatches中的一个。 但是,从我所知道的情况来看,感觉就像是最好的。 也许别人可以做更多的挖掘,find更好的解决scheme?

扩展卡米尔的答案有点:添加以下方法到application_helper.rb:

 def date_mdY(date) if date.nil? "" else date.strftime("%m-%d-%Y") end end 

那么你可以稍微修改一下Kamil的答案:

 <%= f.text_field :some_date, :value => date_mdY(@model_instance.some_date) %> 

然后,您可以在任何其他视图中使用此帮助程序方法。

我正在使用jQuery的dateselect器和date需要在一个特定的格式为了默认date设置正确。 谢谢你的答案卡米尔!

configuration/初始化/ date_format.rb

 ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS[:default] = '%m/%d/%Y' 

视图

 <%= form.text_field :check_in_date, value: model.check_in_date.to_s %> 

这一个使用位置,在你的forms:

 <%= f.text_field :date3, value: ( l @model.date3 if @model.date3? ) %> 

在en.yml(或es.yml)

 en: date: formats: default: "%d/%m/%Y" 

转到您的environment.rb文件并添加以下内容:

 ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!( :default => '%m-%d-%Y' ) 

检查官方文件,如果你想读更多:)

所以我在模型中做了这样的事情

 def start_date super.strftime "%Y/%m/%d %H:%M" end 

假设在模型中有一个名为start_date的列,并且想要在表单中显示另一个格式,只需在模型中覆盖其值。

没有什么需要改变的forms。

 <%= f.text_field :start_date, class: 'form-control' %> 

如果您可以手动设置值,则可以使用created_at.strftime(“%m-%d-%Y”) http://snippets.dzone.com/tag/strftime

我有类似的问题与时间属性/领域。 所以可以这样做:

http://railscasts.com/episodes/32-time-in-text-field

它工作得很好。

但是我挖掘并find了另一个有趣的解决scheme。 一种丑陋的monkeypatch,但在某些情况下,从railscasts可能会更有用。

所以我有一个名为time (ofc它有一个时间types)的列的模型。 这是我的解决scheme:

  after_initialize :init private def init unless time.nil? @attributes['time'] = I18n.l(time, format: :short) end end 

正如你所看到的,我将格式化将由time_before_type_cast方法返回的time_before_type_cast 。 所以我已经正确地格式化了我的文本input(由FormBuilder呈现)的时间,但是如果用户把错误,如10;23我仍然有这个,并在下一个请求将由FormBuilder::text_field呈现。 所以用户有机会修复他的可怜的错误。

这个工作有两个部分,第三个部分要做好。 如果您只想复制粘贴,请继续并滚动到最后。

第1部分:获取Date根据需要设置自己的格式

在ActiveSupport中有很多Date的核心扩展 ,但是他们都没有创build一个新的date类。 如果您正在使用Date ,这是Rails在数据库中有date列时返回的内容,那么将该date转换为string的方法是Date#to_formatted_sActiveSupport扩展添加这个方法,并且它们将to_s方法别名,所以当你调用Date#to_s (可能是隐含的)的时候,你会得到Date.to_formatted_s

有两种方法可以更改to_formatted_s使用的格式:

  1. 传递您想使用的格式的名称(此参数将用于查找Date::DATE_FORMATS的格式)。
  2. 更改格式:default映射到。 由于to_formatted_s设置默认值:default ,所以当您调用Date#to_s而不传递参数时,将获得由Date::DATE_FORMATS[:default]指定的格式。 您可以在应用程序范围内覆盖默认值,如下所示:

     Date::DATE_FORMATS[:default] = "%m/%d/%Y" 

我有这样的初始化程序像config/initializers/date_formats.rb 。 这是粗糙的,不支持改变你的本地化,但得到Date#to_s返回所需的格式没有任何猴子修补或显式转换您的datestring和传递参数。

第2部分:获取用户input的date转换为date对象

默认情况下,您的ActiveRecord实例将使用好的ol ISO 8601来转换date列 ,如下所示: yyyy-mm-dd

如果它不完全匹配那个格式(例如,它是斜线分隔),它回落到使用Ruby的Date._parse ,这是稍微宽松,但仍然期望看到几天,几个月,然后几年: dd/mm/yyyy

为了让Rails以收集它们的格式parsingdate,你只需要用你自己的方法replacecast_value方法。 你可以 monkeypatch ActiveRecord::Types::Date ,但是从它inheritance自己的types并不难。

我喜欢用Chronic来parsing用户input的datestring,因为它提供了更多的东西,比如“Tomorrow”或者“Jan 99”,甚至像“5 / 6-99”(1999年5月6日)那样的拼音input。 由于Chronic返回一个Time的实例,我们正在覆盖所提供的cast_value方法,所以我们需要在它上面调用to_date

 class EasyDate < ActiveRecord::Type::Date def cast_value(value) default = super parsed = Chronic.parse(value)&.to_date if value.is_a?(String) parsed || default end end 

现在我们只需告诉ActiveRecord使用EasyDate而不是ActiveRecord::Type::Date

 class Pony < ApplicationRecord attribute :birth_date, EasyDate.new end 

这是有效的,但是如果你像我一样,你现在想要做更多的工作,以便将来可以节省3秒钟。 如果我们可以告诉ActiveRecord总是使用EasyDate作为date的列? 我们可以。

第3部分:让Rails自动处理

ActiveRecord为您提供各种有关您的模型的信息,用于处理幕后的所有“魔术”。 它给你的方法之一是attribute_types 。 如果你在你的控制台上运行,你会回到呕吐 – 这有点吓人,你只是去“哦,不知道”。 如果你像某种奇怪的东西一样呕吐,那只是一个哈希,看起来像这样:

 { column_name: instance_of_a_type_object, ... } 

不是可怕的东西,但是因为我们开始嘲笑内部,这些instance_of_a_type_object的检查输出可能最终看起来钝和“封闭”。 喜欢这个:

 #<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Money:0x007ff974d62688 

谢天谢地,我们真的只关心一个: ActiveRecord::Types::Date ,所以我们可以缩小它:

 date_attributes = attribute_types.select { |_, type| ActiveRecord::Type::Date === type } 

这给了我们一个我们想要使用EasyDate循环使用的属性列表。 现在我们只需要告诉ActiveRecord就像上面那样在这些属性上使用EasyDate:

 date_attributes.each do |attr_name, _type| attribute attr_name, EasyDate.new end 

而这基本上是这样做的,但我们需要把它们粘在一起。 如果你使用的是ApplicationRecord你可以放下这个权限,然后离开比赛:

 def inherited(klass) super klass.attribute_types.select { |_, type| ActiveRecord::Type::Date === type }.each do |name, _type| klass.attribute name, EasyDate.new end end 

如果你不想“污染” ApplicationRecord ,你可以像我一样做,并创build一个模块,并扩展ApplicationRecord 。 如果您使用ApplicationRecord ,则需要创build模块并扩展ActiveRecord::Base

 module FixDateFormatting # the above `inherited` method here end # Either this... class ApplicationRecord < ActiveRecord::Base extend FixDateFormatting end # ...or this: ActiveRecord::Base.extend(FixDateFormatting) 

TL; DR – 复制粘贴的内容

如果您不关心如何以及如何使其工作,您可以:

  1. gem "chronic"添加到您的Gemfile和bundle install
  2. 确保你的模型inheritance自ApplicationRecord
  3. config/initializers/date_formatting.rb文件的下面复制代码
  4. 重新开始
  5. 一切都应该现在只是工作™

以下是要复制的代码:

 Date::DATE_FORMATS[:default] = "%m/%d/%Y" module FixDateFormatting class EasyDate < ActiveRecord::Type::Date def cast_value(value) default = super parsed = Chronic.parse(value)&.to_date if value.is_a?(String) parsed || default end end def inherited(subclass) super date_attributes = subclass.attribute_types.select { |_, type| ActiveRecord::Type::Date === type } date_attributes.each do |name, _type| subclass.attribute name, EasyDate.new end end end Rails.application.config.to_prepare do ApplicationRecord.extend(FixDateFormatting) end