Как условно избежать ошибки 'nil не может быть приведен к Integer' - PullRequest
1 голос
/ 11 февраля 2020

Используя приведенный ниже код, я получаю ошибку 'nil не может быть приведен к Integer' в Rails.

На мой взгляд:

<%= account_totals %>

В помощнике вида :

def account_totals
  if @user.accounts.any?
    account_total = 0
    @user.accounts.each do |account|
      account_total += account.amount
    end
    account_total
  end
end

Это происходит потому, что у пользователя нет связанных с ним учетных записей, поэтому значение account.percent равно nil. Однако сначала я проверяю, есть ли у пользователя какие-либо учетные записи, поэтому этот код не должен запускаться, если у них нет учетных записей.

Как правильно суммировать итоговые суммы из учетные записи пользователей?

Ответы [ 4 ]

1 голос
/ 11 февраля 2020

Просто сделайте это в базе данных:

@users = User.select('users.*', 'SUM(accounts.amount) AS account_totals')
             .left_joins(:accounts)
             .group(:id)

Большинство баз данных объединят нулевые значения в 0 при использовании SUM.

Если вы просто выбираете одного пользователя и два запроса - это нормально Вы можете использовать ActiveRecord::Calcations#sum.

@user = User.find(1)
account_totals = @user.accounts.sum(:amount)

Не делайте этого во время циклического просмотра коллекции пользователей, поскольку это создает проблему с запросом n + 1.

1 голос
/ 11 февраля 2020
def account_totals
  @user.accounts.map(&:amount).compact.sum
end

Если учетных записей нет, @user.accounts будет пустой коллекцией. Пустые коллекции по-прежнему отвечают на все те же методы, что и заполненные, поэтому вызовы map и sum будут работать - они просто будут пустыми.

nil s можно удалить из коллекции с помощью .compact

Если честно, ваш вопрос немного запутан; вы ссылаетесь на account.percent, которого нет в вашем фрагменте кода; и если коллекция accounts пуста, то += НЕ будет работать. Поскольку вы получаете ошибку принуждения, мы должны предположить, что этот код работает, а account.amount равен nil. Если это имеет смысл, рассмотрите значение по умолчанию от amount до 0 в модели Account. В противном случае используйте compact для фильтрации nil s из массивов, как я уже говорил выше. Если вы ДЕЛАЕТЕ по умолчанию от amount до 0, вы можете использовать фрагмент в комментарии @AbM для максимальной ясности и минимализма.

1 голос
/ 11 февраля 2020

Поскольку некоторые из account записей имеют сумму nil, вы можете преобразовать их в integer, позвонив по номеру to_i или с плавающей точкой по to_f, здесь account.amount где-то возвращает nil, сделайте это

account_total += account.amount.to_i

Устранит ошибку. Но так как amount является столбцом цифры c, вам лучше установить значение по умолчанию равным 0 в миграциях на уровне БД.

или использовать sum

account_total = @user.accounts.sum(:amount)

Это избегает значений nil и запускает SQL sum

0 голосов
/ 11 февраля 2020
def account_totals
    # Initalizing total to 0
    account_total = 0
  if @user.accounts.any?
    @user.accounts.each do |account|
      account_total += account.amount
    end
  end
  #Allways return total, that wil be 0 or other value
 account_total
end

В вашем коде, если у пользователя нет аккаунта, возвращается nil

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...