是否可以将mongoid field
配置为Struct
而不是Hash
反序列化? (with defaults)
我的用例:在我的模型中将订阅计划存储为哈希的公司。
以前作为哈希
class Company
include Mongoid::Document
field :subscription, type: Hash, default: {
ends_at: 0,
quantity: 0,
started_at: 0,
cancelled: false,
}
我希望我不必写Company.first.subscription[:ends_at]
,我宁愿写Company.subscription.ends_at
我认为以下内容会更好用
class Company
include Mongoid::Document
field :subscription_plan, type: Struct, default: Struct.new(
:ends_at, :quantity, :started_at, :cancelled
) do
def initialize(
ends_at: nil,
quantity: 0,
starts_at: nil,
cancelled: false
); super end
end
end
如果可以在课程中定义计划,那就更好了
class SubscriptionPlan < Struct.new(
ends_at, :quantity, :starts_at, :cancelled
) do
def initialize(
ends_at: nil,
quantity: 0,
starts_at: nil,
cancelled: false
); super; end
end
class Company
field :subscription_plan, type: SubscriptionPlan, default: SubscriptionPlan.new
end
我怎样才能让它发挥作用?
答案 0 :(得分:1)
带上一粒盐,因为我从未使用过MongoDB或Mongoid。 仍然,谷歌搜索&#34;自定义类型&#34;把我带到了documentation。
以下是自定义类型示例的改编版本:
class SubscriptionPlan
attr_reader :ends_at, :quantity, :started_at, :cancelled
def initialize(ends_at = 0, quantity = 0, started_at = 0, cancelled = false)
@ends_at = ends_at
@quantity = quantity
@started_at = started_at
@cancelled = cancelled
end
# Converts an object of this instance into a database friendly value.
def mongoize
[ends_at, quantity, started_at, cancelled]
end
class << self
# Get the object as it was stored in the database, and instantiate
# this custom class from it.
def demongoize(array)
SubscriptionPlan.new(*array)
end
# Takes any possible object and converts it to how it would be
# stored in the database.
def mongoize(object)
case object
when SubscriptionPlan then object.mongoize
when Hash then SubscriptionPlan.new(object.values_at(:ends_at, :quantity, :started_at, :cancelled)).mongoize
else object
end
end
# Converts the object that was supplied to a criteria and converts it
# into a database friendly form.
def evolve(object)
case object
when SubscriptionPlan then object.mongoize
else object
end
end
end
end
class Company
include Mongoid::Document
field :subscription, type: SubscriptionPlan, default: SubscriptionPlan.new
end
这会让你更接近你想做的事情。
请注意,默认情况下,每个公司都会共享默认的SubscriptionPlan
。如果您修改一家公司的默认计划,可能会导致一些奇怪的错误。
答案 1 :(得分:0)
我意识到我只是重新实现没有ID的嵌套文档。最后,我决定切换到subscription
的普通嵌入式文档,因为有一个额外的ID字段不是问题,我得到mongoid范围作为奖励。如果我想支持任何密钥,我总是可以添加Mongoid::Attributes::Dynamic
。
然而,问题和其他答案仍然适用于想要创建自己的类型的人。