2015-06-17 3 views
1

У меня проблема с запутанностью. Вот он:Сумма возвращает значение, когда должно возвращаться 0

[12] pry(EstimatedTime)> EstimatedTime.where(user_id: User.current.id, plan_on: date).pluck(:hours) => [] 
[13] pry(EstimatedTime)> EstimatedTime.where(user_id: User.current.id, plan_on: date).sum(:hours) => 3.0 

Что это за магия?

Это утверждение находится в методе модели, который вызывается из представления. До этого, в действии контроллера, я вызываю другой метод той же модели, который выполняет массовое создание записей в транзакции.

def self.save_all(records) 
    transaction do 
    records.each do |record| 
     record.save! 
    end 
    end 
    rescue ActiveRecord::RecordInvalid 
    return false 
end 

Исключение составляет бросок, метод возвращает false, визуализируется представление, и это происходит.

UPD Я нашел обходной путь, заменив .sum с .pluck(:hours).sum, но я до сих пор понятия не имею, почему мой первый способ сделать это не удается.

+0

Что вы получаете, если вы делаете «EstimatedTime.where (user_id: User.current.id, plan_on: date) .map {| et | et.hours} '? –

+0

@MaxWilliams Я получаю пустой массив. – Roman

+0

Что такое SQL-запросы? –

ответ

0

David Aldrige Как указано в комментариях к вопросу, проблема заключалась в том, что .sum(:hours) использовал кешированные данные, а .pluck(:hours) фактически изучал базу данных.

Почему в базе данных и в кеше запросов содержатся разные данные? Ну, похоже, что в Rails 3 (я, вероятно, должен был указать мою версию рельсов, когда задавал вопрос), транзакция не удалила бы базу данных, но оставила кэш запросов неповрежденным. Это привело к временной несогласованности данных между базой данных и кешем. Это было исправлено в Rails 4, как указано в выпуске this.

Решение 1 ака, который я выбрал для себя

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

def self.save_all(records) 
    transaction do 
    records.each do |record| 
     record.save! 
    end 
    end 
    rescue ActiveRecord::RecordInvalid 
    self.connection.clear_query_cache 
    return false 
end 

Решение 2

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

EstimatedTime.where(user_id: User.current.id, plan_on: date).pluck(:hours).sum

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

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