如何实现带本地化日期的Rails Where查询并指定I18n区域?
嘿,我来帮你搞定这两个Rails本地化相关的需求,分两部分给你拆解说明:
首先要明确:数据库存储的日期/时间是标准格式(比如YYYY-MM-DD),而本地化日期是展示层的格式(比如西班牙语的DD/MM/YYYY)。如果你的需求是用「本地化格式的日期字符串」作为查询条件,核心是先把本地化字符串解析成数据库能识别的Date/DateTime对象,再执行查询。
具体步骤:
解析本地化日期字符串
利用Rails的I18n模块,结合你配置的本地化日期格式来解析。比如假设你已经在config/locales/es.yml里配置了日期格式:es: date: formats: default: "%d/%m/%Y"那么解析西班牙语格式的日期字符串可以这样做:
# 假设用户传入的本地化日期字符串是 "15/10/2024" localized_date_str = "15/10/2024" # 根据es区域的默认日期格式解析成Date对象 parsed_date = Date.strptime(localized_date_str, I18n.t('date.formats.default', locale: :es))用解析后的对象执行Where查询
拿到Date/DateTime对象后,就可以正常写ActiveRecord查询了,比如查询某一天创建的用户:# 查询15/10/2024当天创建的所有用户 users = User.where(created_at: parsed_date.all_day)
如果是处理DateTime(带时间),逻辑类似,只是用DateTime.strptime,并对应配置的时间格式即可。
这里要注意:ActiveRecord查询返回的是模型实例,实例的日期/时间属性是原生的Date/DateTime类型,本身没有“格式”——格式是在把属性转换成字符串的时候才会应用本地化规则。
所以要让结果遵循:es的本地化格式,核心是在格式化输出的时候切换到:es区域,有两种常用方式:
方式1:临时切换区域包裹查询和格式化逻辑
用I18n.with_locale(:es)块临时切换区域,块内所有的本地化操作都会使用:es规则:
I18n.with_locale(:es) do # 执行查询 users = User.where(name: "John") # 格式化输出日期,会自动使用es的格式 users.each do |user| puts "创建时间:#{I18n.localize(user.created_at)}" # 输出类似 "创建时间:15/10/2024" puts "详细时间:#{user.created_at.to_s(:long)}" # 输出类似 "详细时间:15 de octubre de 2024 14:30:00" end end
方式2:在模型中定义本地化方法
如果需要频繁返回西班牙语格式的日期,可以在模型里封装方法,直接指定:es区域:
class User < ApplicationRecord # 返回西班牙语格式的创建时间 def created_at_es I18n.localize(created_at, locale: :es, format: :long) end # 返回西班牙语格式的更新时间 def updated_at_es I18n.localize(updated_at, locale: :es) end end # 使用示例 users = User.where(name: "John") puts users.first.created_at_es # 直接输出西班牙语格式的日期
如果是要序列化模型为JSON时使用:es格式,可以在序列化器(比如Jbuilder、ActiveModelSerializers)里指定区域,比如Jbuilder示例:
# app/views/users/show.json.jbuilder I18n.with_locale(:es) do json.extract! @user, :id, :name json.created_at I18n.localize(@user.created_at) end
内容的提问来源于stack exchange,提问作者user1666543

