对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

自定义字段行为

在本指南中,您可以学习;了解如何自定义 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 loadedfield :submitted_at, type: Time, default: Time.now # Time.now is set to the time the document is instantiatedfield :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: Stringend

Mongoid 将 name字段存储为 "n",但您仍然可以在应用程序中作为 name访问权限该字段。

您可以使用 alias_attribute 选项为字段创建别名。 指定别名不会改变 Mongoid 在数据库中存储字段的方式,但它允许您在应用程序中通过不同名称访问权限字段。

以下示例为 name字段指定别名:

class Band include Mongoid::Document field :name, type: String alias_attribute :n, :nameend

要删除字段别名,可以使用 unalias_attribute 选项。 以下示例删除 name字段的别名:

class Band unalias_attribute :nend

您还可以使用 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: trueend

默认情况下,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 哈希中。

您可以指定与字段同名的方法并调用 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) endend

您可以通过指定 attr_readonly 选项将字段指定为只读。 这允许您创建具有属性的文档,但不能更新它们。

以下示例创建一个 Band 类并将 name字段指定为只读:

class Band include Mongoid::Document field :name, type: String field :origin, type: String attr_readonly :nameend

如果调用批量更新方法(例如 update_attributes),并传入只读字段,则 Mongoid 会忽略该只读字段并更新所有其他字段。 如果您尝试显式更新只读字段,Mongoid 会引发 ReadonlyAttribute 异常。

注意

调用原子持久性操作符(例如 bit 和 inc)仍会保留对只读字段的更改。

要学习;了解如何将整个模型指定为只读,请参阅执行数据操作指南中的只读文档部分。

Mongoid 通过使用 i18n gem 支持本地化字段。当您本地化一个字段时,Mongoid 会将该字段存储为区域设置键和值的哈希值。访问字段的行为与访问字符串值的行为相同。 您可以本地化任何字段类型的字段。

以下示例创建了一个带有本地化 review字段的 Product 类:

class Product include Mongoid::Document field :review, type: String, localize: trueend I18n.default_locale = :enproduct = Product.newproduct.review = "Marvelous!"I18n.locale = :deproduct.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!" }

您可以通过启用i18n 回退功能来为本地化字段指定回退。

通过在您的环境中设置 config.i18n.fallbacks 配置设置并设置回退语言,在 Rails应用程序中启用回退:

config.i18n.fallbacks = trueconfig.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: falseend

查询本地化字段时,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!" }

注意

如果要对本地化字段进行广泛查询,我们建议为要查询的每个区域设置索引。