我正在尝试跟踪用户的当前,之前和所选(期末更改)订阅状态。
在月度期间结束时,如果chosen_subscription != current_subscription
,则current_subscription
会发生变化。
class User
include Mongoid::Document
embeds_one :previous_subscription, class_name: "Subscription"
embeds_one :current_subscription, class_name: "Subscription"
embeds_one :chosen_subscription, class_name: "Subscription"
end
class Subscription
include Mongoid::Document
embedded_in :user
field :plan, type: String
field :credits, type: Integer
field :price_per_credit, type: BigDecimal
field :start, type: Date
field :end, type: Date
end
Mongoid希望我以一种对我没有意义的方式更多地指定它:
Mongoid::Errors::AmbiguousRelationship:
Problem:
Ambiguous relations :previous_subscription, :current_subscription, :chosen_subscription defined on User.
Summary:
When Mongoid attempts to set an inverse document of a relation in memory, it needs to know which relation it belongs to. When setting :user, Mongoid looked on the class Subscription for a matching relation, but multiples were found that could potentially match: :previous_subscription, :current_subscription, :chosen_subscription.
Resolution:
On the :user relation on Subscription you must add an :inverse_of option to specify the exact relationship on User that is the opposite of :user.
当我覆盖现有的current_subscription时会发生这种情况。我想,此时,Mongoid想要取消注册旧订阅的用户订阅。
当然,每个订阅对象只属于一个用户和user == user.previous_subscription.user == user.current_subscription.user == user.chosen_subscription.user
然而,告诉Subscription
user
与三者中的任何一个相反,我都没有意义。
我应该如何构建它?
答案 0 :(得分:5)
正如它所说:你必须添加:inverse_of选项。试试这个:
class User
include Mongoid::Document
embeds_one :previous_subscription, class_name: "Subscription", inverse_of: :previous_subscription
embeds_one :current_subscription, class_name: "Subscription", inverse_of: :current_subscription
embeds_one :chosen_subscription, class_name: "Subscription", inverse_of: :chosen_subscription
end
class Subscription
include Mongoid::Document
embedded_in :user, inverse_of: :previous_subscription
embedded_in :user, inverse_of: :current_subscription
embedded_in :user, inverse_of: :chosen_subscription
field :plan, type: String
field :credits, type: Integer
field :price_per_credit, type: BigDecimal
field :start, type: Date
field :end, type: Date
end
答案 1 :(得分:0)
每个mongoid关系都有一个反比关系,用于正确设置两个边。大多数情况下,它可以根据命名约定,使用的类等正确识别,但有时您需要明确定义它们。
mongoid问题在于抱怨这里User
模型中定义的关系是模糊的,因为mongoid无法识别它们中的哪一个映射到subscription.user
中的Subscription
关系。此外,当使用subscription.user = some_user
时,mongoid无法识别您是否需要在用户中将previous_subscription
,current_subscription
或chosen_subscription
设置为订阅对象。即使你没有明确地调用这个方法,你也可以面对这些问题,因为mongoid试图在设置关系时设置反转。
我不确定这是否是构建系统的正确方法,但您可以在关系中定义inverse_of: nil
以告诉mongoid在设置关系时不设置反向关系。只有在您不需要在代码中使用subscription.user=
时才应使用此方法。 subscription.user
也可能存在问题,但如果您绝对需要,可以使用未记录的方法doc._parent
或doc._root
。这种方法虽然解决了这个问题,但也有其自身的缺点。我试图用以下代码在这里显示它们:
class Tester
include Mongoid::Document
field :name, type: String
embeds_one :first_module, class_name: 'TestModule', inverse_of: nil
embeds_one :last_module, class_name: 'TestModule', inverse_of: nil
end
class TestModule
include Mongoid::Document
field :name, type: String
# not needed as such, but required to tell mongoid that this is a embedded document
embedded_in :tester, inverse_of: nil
end
t1 = Tester.new(name: 't1')
m1 = t1.build_first_module(name: 't1m1')
m2 = t1.build_last_module(name: 't1m2')
t1.first_module == m1 #=> true
t1.last_module == m2 #=> true
m1.tester #=> nil
m2.tester #=> nil
t1.save
t1 = Tester.last
m1 = t1.first_module
m2 = t1.last_module
t1.first_module == m1 #=> true
t1.last_module == m2 #=> true
m1.tester #=> nil
m2.tester #=> nil