2016-04-27 2 views
0

Я столкнулся с проблемой в течение длительного времени. Код у меня есть следующие:Модель не работает в валидации, но создается

class BrokenModel < ActiveRecord::Base 
    validates_with BrokenValidator 

    has_many :association_name 
end 

class BrokenValidator < ActiveModel::Validator 
    def validate record 
    @record = record 

    check_alerted 
    end 

    private 

    def check_alerted 
    return if @record.association_name.to_a.empty? 

    alerted = <test for alerted> 
    if alerted 
     @record.errors[:base] << "It was alerted recently" 
    end 

    p "check_alerted: #{@record.errors[:base]}" 
    end 
end 

worker.rb

[...] 
BrokenModel.create(association_name: [model1, model2]) 
[...] 

В моих журналах для последнего отпечатка показывает, что проверка прошла только один раз, но я на самом деле несколько записей, созданных для этого модель с association_name подарок.

Мое окружение работает в нескольких потоках и нескольких ядрах, но поскольку записи создаются в нескольких минутах друг от друга, это не проблема параллелизма, если исключение в отдельном потоке не влияет на создание модели.

Просто ради любопытства, это работает в рабочем работнике Sidekiq.

Редактировать

Так что я заметил в моих журналах, что это может быть проблемой параллелизм. Так вот что происходит:

  • экземпляр 1 проверки: насторожило недавно: не удалось (это насторожило недавно)
  • экземпляр 2 проверки: насторожило недавно: пройденная
  • экземпляр 2 проверки: другие проверки: не удалось (Другое подтверждение)
  • экземпляра 2 ошибки создания: Он был недавно предупрежден + Другие проверки
  • ошибка создания экземпляра 1: Нет

Любая подсказка, если в ActiveModel есть какой-либо вид небезопасности потока: Validator или @record могут быть перезаписаны/разделены другими потоками?

+0

что означает '<тест для предупреждения>', может ли это объяснить, PLS? – 7urkm3n

+0

Это метод, который проверяет redis на наличие и идентификатор. Это не так полезно, потому что, если метод возвращал неправильные значения, он либо бросал исключение, либо доходил бы до check_alerted log empty. – felipeclopes

+0

Есть ли вероятность того, что имя_соединения будет пустым на этапе проверки, и заполнится позже в цикле сохранения, даже если он введен в команду create? – felipeclopes

ответ

2

Добавление ошибок в запись НЕ делает его недействительным. Фактически, когда модель проверяется перед сохранением, все предыдущие ошибки, включая тот, который вы добавляете в свой код, стираются.

Проделайте эту проверку в модели ... Не в рабочем состоянии.

validate :check_alerted 

def check_alerted 
    return if association_name.to_a.empty? 
    alerted = test 
    if <test for alerted> 
     errors.add(:base, "It was alerted recently") 
    end 
end 
+0

К сожалению, код не заполнен. Создание выполняется в Sidekiq, но проверка находится в модели. Просто исправить вопрос. – felipeclopes

+0

Это в модели, но вы имеете в виду переменную экземпляра '@ record'? – SteveTurczyn

+0

Я обновил код – felipeclopes

Смежные вопросы