Удаление или переопределение проверки ActiveRecord, добавленной суперклассом или смешиванием

Я использую Разрешение для аутентификации в моем приложении направляющих. Clearance::User смешивание добавляет несколько проверок к моему User модель, но существует один из них, что я хотел бы удалить или переопределить. Каков лучший способ сделать это?

Рассматриваемая проверка

validates_uniqueness_of :email, :case_sensitive => false

который сам по себе не плох, но я должен был бы добавить :scope => :account_id. Проблема - это, если я добавляю это к моему User модель

validates_uniqueness_of :email, :scope => :account_id

Я получаю обе проверки, и одно Разрешение добавляет, более строго, чем мой, таким образом, мой не имеет никакого эффекта. Я должен удостовериться та единственная шахта выполнения. Как я делаю это?

21
задан John Bachir 15 August 2014 в 21:24
поделиться

2 ответа

В итоге я "решил" проблему следующим образом:

  1. ищем ошибку в атрибуте :email типа :taken
  2. проверяем, уникален ли email для этой учетной записи (именно эту проверку я и хотел сделать)
  3. удаляем ошибку, если email уникален для этой учетной записи.

Звучит разумно, пока вы не прочитаете код и не узнаете, как я удаляю ошибку. ActiveRecord::Errors не имеет методов для удаления ошибок после их добавления, поэтому мне приходится хвататься за его внутренности и делать это самому. Супер-пупер-мега-уродливо.

Вот код:

def validate
  super
  remove_spurious_email_taken_error!(errors)
end

def remove_spurious_email_taken_error!(errors)
  errors.each_error do |attribute, error|
    if error.attribute == :email && error.type == :taken && email_unique_for_account?
      errors_hash = errors.instance_variable_get(:@errors)
      if Array == errors_hash[attribute] && errors_hash[attribute].size > 1
        errors_hash[attribute].delete_at(errors_hash[attribute].index(error))
      else
        errors_hash.delete(attribute)
      end
    end
  end
end

def email_unique_for_account?
  match = account.users.find_by_email(email)
  match.nil? or match == self
end

Если кто-то знает лучший способ, я буду очень благодарен.

6
ответ дан 29 November 2019 в 21:47
поделиться

У меня недавно была эта проблема, и после того, как Google не дал мне ответы достаточно быстро, я нашел более аккуратное, но все еще неидеальное решение этой проблемы . Теперь это не обязательно сработает в вашем случае, поскольку кажется, что вы используете уже существующие суперклассы, но для меня это был мой собственный код, поэтому я просто использовал параметр: if с проверкой типа в суперклассе.

def SuperClass
  validates_such_and_such_of :attr, :options => :whatever, :if => Proc.new{|obj| !(obj.is_a? SubClass)}
end

def SubClass < SuperClass
  validates_such_and_such_of :attr
end

В случае подклассов, состоящих из нескольких файлов

def SuperClass
  validates_such_and_such_of :attr, :options => :whatever, :if => Proc.new{|obj| [SubClass1, SubClass2].select{|sub| obj.is_a? sub}.empty?}
end

def SubClass1 < SuperClass
  validates_such_and_such_of :attr
end

def SubClass2 < SuperClass
end
4
ответ дан 29 November 2019 в 21:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: