Rails: сумма значений во всех транзакциях, которые принадлежат Activity - PullRequest
1 голос
/ 17 июня 2011

Я немного похож на Rails n00b, так что извините, если это действительно глупый вопрос.

В этом приложении есть две ключевые модели:

  • Activity - котораясодержит такие данные, как страна получателя, финансирующая организация
  • Транзакция - которая содержит такие данные, как то, сколько денег (стоимость) было совершено или выплачено (тип транзакции), когда, кому и т. д.

Все транзакции вкладываются в действие.Каждое действие имеет несколько транзакций.Они связаны вместе посредством activity_id.has_many: Transactions и assign_to: activity определены соответственно в моделях Activity и Transaction Models.

Итак: все это прекрасно работает, когда я пытаюсь получить подробную информацию о транзакциях для одного действия - либо при просмотреотдельное действие (активность-> показать) или циклическое выполнение действий на странице всех действий (активность-> индекс).Я просто звоню

@activities.each do |activity|
    activity.transactions.each do |transaction|
        transaction.value # do something like display it
    end
end

Но то, что я сейчас действительно хочу сделать, - это получить сумму всех транзакций для всех действий (при условии: условия для действия).

Что лучшеспособ сделать это?Я думаю, я мог бы сделать что-то вроде:

@totalvalue = 0
@activities.each do |activity|
    activity.transactions.each do |transaction|
        @totalvalue = @totalvalue + transaction.value
    end 
end

... но это не кажется очень чистым и заставляет сервер выполнять ненужную работу.Я полагаю, это может быть связано с моделью ...?!sum () - это еще один вариант, может быть?

Это частично произошло, потому что я хочу показать общую сумму, идущую в каждую страну, за хорошие пузырьки на первой странице:)

Большое спасибоза любую помощь!

Обновление:

Спасибо за все ответы!Итак, теперь это работает:

@thiscountry_activities.each do |a|
    @thiscountry_value = @thiscountry_value + a.transactions.sum(:value)
end

Но это не работает:

@thiscountry_value = @thiscountry_activities.transactions.sum(:value)

Это выдает эту ошибку:

undefined method `transactions' for #<Array:0xb5670038>

Похоже, у меня есть некоторыесвоего рода проблема ассоциации.Вот как настраиваются модели:

class Transaction < ActiveRecord::Base
    belongs_to :activity
end

class Activity < ActiveRecord::Base
    has_and_belongs_to_many :policy_markers
    has_and_belongs_to_many :sectors
    has_many :transactions
end

Я думаю, что это, вероятно, довольно простая проблема, но я не могу понять, что происходит.Две модели связаны друг с другом через id (в Activity) и activity_id (в транзакциях).

Еще раз спасибо!

Ответы [ 5 ]

13 голосов
/ 17 июня 2011

Используйте метод Active Record sum, доступный для классов:

Transaction.sum(:value)

Или, как вы хотите, ассоциации:

activity.transactions.sum(:value)
1 голос
/ 12 января 2012

Мой код получился довольно сумбурным, суммируя виртуальные атрибуты.Поэтому я написал этот маленький метод, чтобы сделать это для меня.Вы просто передаете коллекцию и имя метода в виде строки или символа и получаете общее количество.Я надеюсь, что кто-то найдет это полезным.

def vsum collection, v_attr # Totals the virtual attributes of a collection
  total = 0
  collection.each { |collect| total += collect.method(v_attr).call } 
  return total
end

# Example use

total_credits = vsum(Account.transactions, :credit)

Конечно, вам это не нужно, если: credit - столбец таблицы.Вам лучше использовать встроенный метод ActiveRecord выше.В моем случае у меня есть столбец: количество, когда положительным является: кредит, а отрицательным является: дебет.Поскольку: debit и: credit не являются столбцами таблицы, их нельзя суммировать с помощью ActiveRecord.

1 голос
/ 17 июня 2011

Пусть база данных сделает работу:

@total_value = Transaction.sum(:value)

Это дает сумму для всех транзакций. Если у вас уже загружены некоторые действия, вы можете отфильтровать их следующим образом:

@total_value = Transaction.where(:activity_id => @activities.map(&:id)).sum(:value)

Вы можете сделать это одним запросом:

@total_value = Transaction.joins(:activity).where("activities.name" => 'foo').sum(:value)
0 голосов
/ 17 июня 2011

Вы могли бы сделать

@total_value = activity.transactions.sum(:value)

http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html

0 голосов
/ 17 июня 2011

Как я понял, вы хотели бы иметь сумму всех значений таблицы транзакций.Вы можете использовать SQL для этого.Я думаю, что это будет быстрее, чем в Ruby.

выберите сумму (значение) в качестве транзакции_value_sum из транзакции;

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