自定义字段行为
Overview
在本指南中,您可以学习;了解如何自定义 Mongoid 模型中字段的行为。
指定默认值
您可以使用 default
选项将字段配置为默认值。 默认字段值可以是固定值或 Proc
值。
以下示例为 state
字段指定固定的默认值:
class Order include Mongoid::Document field :state, type: String, default: 'created' end
以下示例为 fulfill_by
字段指定 Proc
默认值:
class Order include Mongoid::Document field :fulfill_by, type: Time, default: ->{ Time.now + 3.days } end
注意
加载类时,驾驶员会计算不是Proc
实例的默认值。实例化文档时,驾驶员会计算Proc
值。以下默认字段值不会产生等效结果:
# Time.now is set to the time the class is loaded field :submitted_at, type: Time, default: Time.now # Time.now is set to the time the document is instantiated field :submitted_at, type: Time, default: ->{ Time.now }
您可以通过在 Proc
实例中使用 self
关键字设立取决于文档状态的默认值。 以下示例将 fulfill_by
默认值设置为取决于 submitted_at
字段的状态:
field :fulfill_by, type: Time, default: ->{ self.submitted_at + 4.hours }
默认下,Mongoid 在设置和初始化所有其他属性后应用 Proc
默认值。 要在设置其他属性之前应用默认,请将 pre_processed
选项设立为 true
,如以下示例所示:
field :fulfill_by, type: Time, default: ->{ Time.now + 3.days }, pre_processed: true
提示
始终将 pre-processed
选项设立为 true
,以便为 _id
字段设立默认的Proc
值。
指定存储名称
您可以指定一个单独的字段名称以存储在数据库中,同时在应用程序中仍按字段的原始名称引用该字段。 这可以节省存储空间,因为MongoDB将所有字段信息与每个文档一起存储。
您可以使用 as:
关键字设立备用存储名称。 以下示例创建了一个名为 name
的字段,Mongoid 将其存储在数据库中为 n
:
class Band include Mongoid::Document field :n, as: :name, type: String end
Mongoid 将 name
字段存储为 "n"
,但您仍然可以在应用程序中作为 name
访问权限该字段。
字段别名
您可以使用 alias_attribute
选项为字段创建别名。 指定别名不会改变 Mongoid 在数据库中存储字段的方式,但它允许您在应用程序中通过不同名称访问权限字段。
以下示例为 name
字段指定别名:
class Band include Mongoid::Document field :name, type: String alias_attribute :n, :name end
要删除字段别名,可以使用 unalias_attribute
选项。 以下示例删除 name
字段的别名:
class Band unalias_attribute :n end
您还可以使用 unalias_attribute
从 _id
字段中删除预定义的 id
别名。 这可用于在 _id
字段和 id
字段中存储不同的值。
字段重新定义
默认情况下,Mongoid 允许您重新定义模型上的字段。 要在重新定义字段时引发错误,请将 mongoid.yml
文件中的 duplicate_fields_exception
设立选项设置为 true
。
如果 duplicate_fields_exception
选项设立为 true
,您仍然可以在定义字段时通过将 overwrite
选项设置为 true
来重新定义特定字段。 以下示例定义了 name
字段,然后使用 overwrite
选项重新定义了该字段:
class Person include Mongoid::Document field :name field :name, type: String, overwrite: true end
自定义ID字段
默认情况下,Mongoid 会定义文档上的 _id
字段以包含 Mongoid 自动生成的 BSON::ObjectId
值。 您可以自定义类型,或通过在模型中指定 _id
字段来指定其默认值。
以下示例创建了一个带有自定义 _id
字段的 Band
类:
class Band include Mongoid::Document field :name, type: String field :_id, type: String, default: ->{ name } end
您可以省略 _id
字段的默认值。 如果您没有为该字段指定默认值,Mongoid 将保留没有 _id
值的文档。 对于顶级文档, MongoDB 服务器会自动分配 _id
值。 但是,对于嵌入式文档,服务器不会分配 _id
值。
当您没有为 _id
字段指定值时,Mongoid 不会从服务器检索自动分配的值。 因此,您无法使用 _id
值从数据库中检索文档。
不可转换值
如果某个值无法转换为指定的字段类型,则该值被视为不可转换。示例,在将数组分配给 Integer
字段时,该大量被视为不可转换。
在 v8.0 及更高版本中,Mongoid 会将 nil
分配给不可转换的值。 原始的不可转换值与其字段名称一起存储在 attributes_before_type_cast
哈希中。
自定义 Getter 和 Setter
您可以指定与字段同名的方法并调用 read_attribute
或 write_attribute
方法对原始属性值进行操作,从而覆盖字段的默认getter 和 setter 方法。
以下示例为 Person
类的 name
字段创建自定义 getter 和 setter:
class Person include Mongoid::Document field :name, type: String # Custom getter for 'name' to return the name in uppercase def name read_attribute(:name).upcase if read_attribute(:name) end # Custom setter for 'name' to store the name in lowercase def name=(value) write_attribute(:name, value.downcase) end end
只读属性
您可以通过指定 attr_readonly
选项将字段指定为只读。 这允许您创建具有属性的文档,但不能更新它们。
以下示例创建一个 Band
类并将 name
字段指定为只读:
class Band include Mongoid::Document field :name, type: String field :origin, type: String attr_readonly :name end
如果调用批量更新方法(例如 update_attributes
),并传入只读字段,则 Mongoid 会忽略该只读字段并更新所有其他字段。 如果您尝试显式更新只读字段,Mongoid 会引发 ReadonlyAttribute
异常。
注意
调用原子持久性操作符(例如 bit
和 inc
)仍会保留对只读字段的更改。
本地化字段
Mongoid 通过使用 在 18gem 中 来支持本地化字段。当您本地化一个字段时,Mongoid 会将该字段存储为区域设置键和值的哈希值。 访问字段的行为与访问字符串值的行为相同。 您可以本地化任何字段类型的字段。
以下示例创建了一个带有本地化 review
字段的 Product
类:
class Product include Mongoid::Document field :review, type: String, localize: true end I18n.default_locale = :en product = Product.new product.review = "Marvelous!" I18n.locale = :de product.review = "Fantastisch!" product.attributes # Outputs: { "review" => { "en" => "Marvelous!", "de" => "Fantastisch!" }
您可以通过调用 _translations
方法一次性获取和设立所有翻译:
product.review_translations # Outputs: { "en" => "Marvelous!", "de" => "Fantastisch!" } product.review_translations = { "en" => "Marvelous!", "de" => "Wunderbar!" }
您可以通过启用 i18 n 回退功能来为本地化字段指定回退。
通过在您的环境中设置 config.i18n.fallbacks
配置设置并设置回退语言,在 Rails应用程序中启用回退:
config.i18n.fallbacks = true config.after_initialize do I18n.fallbacks[:de] = [ :en, :es ] end
通过将模块包含到 i18n后端并设置回退语言,在非 Rails 应用程序中启用回退:
require "i18n/backend/fallbacks" I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) I18n.fallbacks[:de] = [ :en, :es ]
启用回退后,如果活动语言没有翻译,则会在指定的回退语言中查找。
您可以在定义字段时将 fallbacks
选项设置为 false,以禁用指定字段的回退语言:
class Product include Mongoid::Document field :review, type: String, localize: true, fallbacks: false end
查询本地化字段时,Mongoid 会自动更改查询条件以匹配当前的区域设置。 以下示例查询 Product
类以获取 en
区域设置的查看:
# Match all products with Marvelous as the review. The current locale is :en. Product.where(review: "Marvelous!") # The resulting MongoDB query filter: { "review.en" : "Marvelous!" }
注意
如果要对本地化字段进行广泛查询,我们建议为要查询的每个区域设置索引。