我有一个rails形式,在text_field中显示日期:
<%= form.text_field :check_in_date %>
Run Code Online (Sandbox Code Playgroud)
日期呈现为 yyyy-mm-dd
我正在试图找出如何将其显示为 mm-dd-yyyy
我尝试添加此配置,但它不起作用.
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(
:default => '%m/%d/%Y'
)
Run Code Online (Sandbox Code Playgroud)
Kam*_*rna 63
简单的一次性解决方案是:value在text_field调用中使用选项而不是向ActiveRecord::Base或添加内容CoreExtensions.
例如:
<%= f.text_field :some_date, value: @model_instance.some_date.strftime("%d-%m-%Y") %>
Run Code Online (Sandbox Code Playgroud)
Tom*_*ssi 38
我把这些添加到我的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"
Run Code Online (Sandbox Code Playgroud)
使用Ruby 1.9.3和Rails 3.2.x.
car*_*iam 11
我花了一些时间查看代码,并且更改DATE_FORMAT将不起作用,因为Rails从不要求日期格式.Felix的设置解决方案:值确实有效,但感觉很麻烦:为什么我必须手动设置特定于日期的文本字段的值?所以这是一个代码,我想要更好的东西.
这是我的简短解决方案,但后来我会解释一下,因为我希望其他人会写出更好的东西:
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
Run Code Online (Sandbox Code Playgroud)
更长的解释:当一个文本字段设置值属性时,它将首先查看选项哈希(这就是为什么菲利克斯的解决方案有效),但如果它不在那里,它将调用form.object.check_in_date_before_type_cast,这将(在一些method_missing魔法之后)将call form.object.attributes_before_type_cast['check_in_date'],将在form.object内的@attributes哈希中查找'check_in_date'.我的猜测是@attributes哈希在获取Ruby对象之前获得直接的MySQL字符串表示(遵循'yyyy-mm-dd'格式),这就是为什么简单地设置DATE_FORMAT本身不起作用的原因.因此,上面的动态方法创建为实际执行类型转换的所有日期对象创建方法,允许您使用格式化日期ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS[:default].
这感觉有点脏,因为'_before_type_cast'的整个目的是为了避免类型转换,这就是那些"可能是龙"的monkeypatches之一.但是,从我所知道的情况来看,感觉就像周围最好的一样.也许其他人可以多做一些挖掘并找到更好的解决方案?
扩展了Kamil的答案:将以下方法添加到application_helper.rb:
def date_mdY(date)
if date.nil?
""
else
date.strftime("%m-%d-%Y")
end
end
Run Code Online (Sandbox Code Playgroud)
然后你可以稍微修改卡米尔的答案:
<%= f.text_field :some_date, :value => date_mdY(@model_instance.some_date) %>
Run Code Online (Sandbox Code Playgroud)
然后,您可以在任何其他视图中使用此帮助程序方法.
我正在使用jQuery日期选择器和特定格式的日期,以便正确设置默认日期.谢谢你的答案卡米尔!
小智 7
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS[:default] = '%m/%d/%Y'
Run Code Online (Sandbox Code Playgroud)
<%= form.text_field :check_in_date, value: model.check_in_date.to_s %>
Run Code Online (Sandbox Code Playgroud)
这个使用位置,以您的形式:
<%= f.text_field :date3, value: ( l @model.date3 if @model.date3? ) %>
Run Code Online (Sandbox Code Playgroud)
在en.yml(或es.yml)的位置
en:
date:
formats:
default: "%d/%m/%Y"
Run Code Online (Sandbox Code Playgroud)
有两个部分来完成这项工作,第三部分让它一切顺利。如果您只想复制粘贴,请继续滚动到最后。
Date根据需要自行格式化在 ActiveSupport中有一堆Date的核心扩展,但它们都没有创建新的日期类。如果您正在使用Date,这是当您date的数据库中有列时 Rails 返回的内容,则将该日期转换为字符串的方法是Date#to_formatted_s. 该ActiveSupport扩展添加这个方法,他们别名to_s方法,所以当你调用Date#to_s(可能是隐含的),你会得到Date.to_formatted_s。
有两种方法可以更改 使用的格式to_formatted_s:
Date::DATE_FORMATS)。更改:default映射到的格式。由于to_formatted_s设置了 的默认值:default,因此当您在Date#to_s不传递参数的情况下调用时,您将获得由Date::DATE_FORMATS[:default]. 您可以在应用程序范围的基础上覆盖默认值,如下所示:
Date::DATE_FORMATS[:default] = "%m/%d/%Y"
Run Code Online (Sandbox Code Playgroud)我在像config/initializers/date_formats.rb. 它很粗糙,不支持随您的本地化进行更改,但可以Date#to_s返回所需的格式,而无需进行任何猴子修补或将日期显式转换为字符串并传入参数。
默认情况下,您的ActiveRecord实例将投日期列使用好醇” ISO 8601,看起来像这样:yyyy-mm-dd。
如果它不完全匹配该格式(例如,它是斜线分隔的),它会回退到使用 Ruby 的Date._parse,这稍微宽松一些,但仍然希望看到天、月、然后是年:dd/mm/yyyy。
要让 Rails 以您收集的格式解析日期,您只需要用cast_value您自己的方法替换该方法。您可以monkeypatch ActiveRecord::Types::Date,但滚动您自己的继承自它的类型并不难。
我喜欢使用Chronic来解析用户输入中的日期字符串,因为它可以忍受更多的狗屎,比如“Tomorrow”或“Jan 1 99”,甚至像“5/6-99”(1999 年 5 月 6 日)这样的疯狂输入。由于 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
Run Code Online (Sandbox Code Playgroud)
现在我们只需要告诉 ActiveRecord 使用EasyDate而不是ActiveRecord::Type::Date:
class Pony < ApplicationRecord
attribute :birth_date, EasyDate.new
end
Run Code Online (Sandbox Code Playgroud)
这行得通,但如果你像我一样,你现在想承担更多的工作,这样你就可以在未来节省 3 秒。如果我们可以告诉 ActiveRecord 总是对只是日期的列使用 EasyDate 会怎样?我们可以。
ActiveRecord 为您提供有关模型的各种信息,用于处理幕后的所有“魔法”。它给我们的方法之一attribute_types。如果你在你的控制台中运行它,你会再次呕吐——这有点可怕,你只会说“哦,没关系”。但是,如果你像某种怪人一样深入研究呕吐物,它只是一个看起来像这样的散列:
{ column_name: instance_of_a_type_object, ... }
Run Code Online (Sandbox Code Playgroud)
不是什么可怕的东西,但由于我们开始研究内部结构,这些检查的输出instance_of_a_type_object最终可能看起来很钝和“封闭”。像这样:
#<ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Money:0x007ff974d62688
Run Code Online (Sandbox Code Playgroud)
值得庆幸的是,我们真的只关心一个: ActiveRecord::Types::Date,所以我们可以缩小范围:
date_attributes = attribute_types.select { |_, type| ActiveRecord::Type::Date === type }
Run Code Online (Sandbox Code Playgroud)
这为我们提供了要升级使用的属性列表EasyDate。现在我们只需要告诉 ActiveRecord 在这些属性上使用 EasyDate 就像我们上面所做的那样:
date_attributes.each do |attr_name, _type|
attribute attr_name, EasyDate.new
end
Run Code Online (Sandbox Code Playgroud)
基本上就是这样,但我们需要把它们粘在一起。如果您正在使用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
Run Code Online (Sandbox Code Playgroud)
如果你不想“污染” ApplicationRecord,你可以像我一样创建一个模块并ApplicationRecord用它扩展。如果您不使用ApplicationRecord,则需要创建模块并扩展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)
Run Code Online (Sandbox Code Playgroud)
如果您不关心如何并且只希望它起作用,您可以:
gem "chronic"到您的 Gemfile 和bundle installApplicationRecordconfig/initializers/date_formatting.rb这是要复制的代码:
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
Run Code Online (Sandbox Code Playgroud)
转到您的environment.rb 文件并添加以下内容:
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!(
:default => '%m-%d-%Y' )
Run Code Online (Sandbox Code Playgroud)
如果您想阅读更多内容,请查看官方文档:)
| 归档时间: |
|
| 查看次数: |
39466 次 |
| 最近记录: |