Validating embedded document in Mongoid based on e

2019-07-07 17:36发布

问题:

I've a class Subscriber which has embeds_many Subscriptions. Subscription has an attribute status. I want to add a validation on status such that only one Subscription can have status 'active' per subscriber. The subscriber can have multiple subscription with status 'purchased' or 'expired' .

回答1:

This should do it:

class Subscriber
  include Mongoid::Document
  embeds_many :subscriptions
  validate :active_subscriptions

  def active_subscriptions
    self.errors.add(:base, 'too many active subscriptions') if 
        subscriptions.where(status: 'active').count > 1
  end
end

class Subscription
  include Mongoid::Document
  embedded_in :subscriber
  field :status, class: 'String'
end

s = Subscriber.create
s.subscriptions.build(status: 'active')
s.save # fires validations on subscriber
s.subscriptions.build(status: 'active')
s.save # wouldn't save

But make sure that you always call save on subscriber, otherwise the validations will not fire on subscriber and you will land in an inconsistent state. In an inconsistent state you might see failing validations later

s = Subscriber.create
s.subscriptions.create(status: 'active') # fires validations on subscription only
s.subscriptions.build(status: 'active').save # fires validations on subscription only

If you need to also validate subscription, when saving subscriber, you cascade callbacks:

embeds_many :subscriptions, cascade_callbacks: true


标签: mongoid