Моноидальная валидация уникальности с помощью scope и assign_to - PullRequest
4 голосов
/ 09 августа 2011

У меня есть следующая модель mongoid, с проверкой объема, чтобы предотвратить несколько голосов за один счет.Каждый голос принадлежит пользователю и группе:

class Vote
  include Mongoid::Document
  field :value, :type => Symbol # can be :aye, :nay, :abstain
  field :type, :type => Symbol  # TODO can delete?

  belongs_to :user
  belongs_to :polco_group

  embedded_in :bill
  validates_uniqueness_of :value, :scope => [:polco_group_id, :user_id, :type]

end

У пользователя есть следующий метод добавления голосования к счету:

  def vote_on(bill, value)    
    if my_groups = self.polco_groups # test to make sure the user is a member of a group
      my_groups.each do |g|
          # TODO see if already voted
          bill.votes.create(:value => value, :user_id => self.id, :polco_group_id => g.id, :type => g.type)
      end
    else
      raise "no polco_groups for this user" # #{self.full_name}"
    end
  end

и класс Bill, который включает много:голосов.Это сделано для того, чтобы пользователь мог связать свой голос с различными группами («Ruby Coders», «Women» и т. Д.) И работает хорошо, за исключением того, что база данных в настоящее время позволяет пользователю голосовать несколько раз за один счет.Как заставить работать следующее?

u = User.last
b = Bill.last
u.vote_on(b,:nay)
u.vote_on(b,:nay) -> should return a validation error

1 Ответ

2 голосов
/ 09 августа 2011

Скорее всего, валидаторы на Vote не запускаются.Вы можете подтвердить это, добавив функцию validates и выведя что-либо или вызвав в ней исключение.

class Vote
  validate :dummy_validator_to_confirmation

  def dummy_validator_to_confirmation
    raise "What the hell, it is being called, then why my validations are not working?"
  end
end

Если после создания вышеприведенных проверок User#vote_on не вызывает исключение, это подтверждает, что обратные вызовы не выполняются дляVote с помощью vote_on метода.Вам нужно изменить код для запуска обратных вызовов на Vote.Вероятно, поменять его так, чтобы он выглядел следующим образом:

def vote_on(bill, value)    
  if my_groups = self.polco_groups # test to make sure the user is a member of a group
    my_groups.each do |g|
        # TODO see if already voted
        vote = bill.votes.new(:value => value, :user_id => self.id, :polco_group_id => g.id, :type => g.type)
        vote.save
    end
  else
    raise "no polco_groups for this user" # #{self.full_name}"
  end
end

На трекере проблем mongoid github существует открытый выпуск *, позволяющий каскадные обратные вызовы для встроенных документов.В настоящее время обратные вызовы запускаются только для документа, на котором выполняются постоянные действия.

...