Search code examples
ruby-on-railssumruby-on-rails-5currencycalculation

Rails 5.1 different sum calculation with multiple currencies


I'm working on a Rails app for my expenses.
Basically I enter some expenses giving a name, description, amount, currency and a date.
For this I have 3 models : User, Spending, Currency with this relations :

class Currency < ApplicationRecord

    has_many :spendings
    has_many :users, through: :spendings

end

class Spending < ApplicationRecord

    belongs_to :user
    belongs_to :currency

end

class User < ApplicationRecord

  has_many :spendings
  has_many :currencies, through: :spendings

end

I'm using the show from the users_controller to index each user expenses. This is what I have in my users_controller

class UsersController < ApplicationController

    def show
        @user_spendings = @current_user.spendings.all.order('date DESC').paginate(:page => params[:page], :per_page => 10)
        @user_amount = @user_spendings.sum(:amount)
    end
end

In this scenario the @user_amount shows me all the expenses from the current_user, the thing is that I have 2 currencies (maybe more in the future) and I would like to show different total amount depending on which currency has been selected when I create a new expense.
I thought about different things here, I tried to do a If statement so that the amount shows only if the currency_id == to 1 if € or to 2 if $ etc... But this wont work well if I add new currencies (and I couldn't make it work).
Maybe a loop ? Loop through the currencies and somehow show the total amount. But you can't do a sum in a loop so I don't know.
Also I'd like it to be flexible, so if in the future I add more currencies that I don't have to touch the code.
Any idea ?
If needed here is my show.html.erb

  <% @user_spendings.each do |spending| %>
  <tr>
    <td><%= spending.title %></td>
    <td><%= spending.description %></td>
    <td><%= '%.02f' % spending.amount %></td>
    <td><%= spending.currency.symb %></td>
    <td><%= spending.date.strftime('%d %B %Y') %></td>
  </tr>
  <% end %>

Thanks alot.


Solution

  • Doing something along the lines of:

    @sums_by_currency = Currency.joins(:spendings).
      select(:symb, 'SUM(spendings.amount) AS amount').
      where(spendings: { id: @user_spendings.map(&:id) }).
      group(:symb)
    

    would allow you to iterate over the currencies as in:

    @sums_by_currency.each do |currency|
      "#{currency.symb}#{currency.amount}"
    end
    

    or

    @sums_by_currency.each do |currency|
      number_to_currency(currency.amount, unit: currency.symb)
    end
    

    in your view.