0

I faced some issue with calculating sum for array items in my rails app. I have 2 models Clients and Teammates. The goal is to calculate profit from Client project.

Models:

class Client < ActiveRecord::Base
  belongs_to :user
  has_many :teammates
  .
  .
  .
  validates :project, presence: true
  validates :budget, presence: true
end

class Teammate < ActiveRecord::Base
  .
  .
  belongs_to :client
  .
  .
  validates :salary, presence: true
end

Controller:

class FrontPagesController < ApplicationController
  def front
    if signed_in?
      mess {current_user}
      @clients.each do |client|
        @client_teammates = current_user.teammates.where(client_project: client.project)
      end
    else
      redirect_to signin_path
    end
  end

  private

    def mess
      #multiple
        @teammates = yield.teammates.all
        @clients = yield.clients.all
      #single 
        @teammate = yield.teammates.build
        @client = yield.clients.build
    end
 end

The formula is: Profit = @client.budget - (sum of @client_teammates salaries) That's where I'm stuck.

I'v tried to do the following

client.budget = 2000

client has 2 teammates with salary of 1000 and 700 accordingly

@clients.each do |client|
    @client_teammates.each do |c_t|
      %li
        a = %w(c_t.salary)
        sum = 0
        %span Profit: #{client.budget - (a.inject{|sum,x| sum + x }).to_i}

Expect output to be: %span Profit: 300 , but got %span Profit: 1000; %span Profit:1300 instead.

1
  • Do you need to calculate and show profit for each client (as you said in the description) or for each teammate of each client (as you wrote in the code)? Commented Nov 11, 2014 at 9:30

1 Answer 1

3
@clients.each do |client|
    @client_teammates.each do |c_t|
      %li
        a = %w(c_t.salary) 
        sum = 0
        %span Profit: #{client.budget - (a.inject{|sum,x| sum + x }).to_i} 
end

Expect output to be: %span Profit: 300 , but got %span Profit: 1000; %span Profit:1300

Take a look at how you're iterating over the teammates and trying to get an aggregate of salaries.

The step a = %w(c_t.salary) should be performed when you still have a collection of teammates but in the context you're using it, you only get one... and you do it twice, each time with a single teammate.

Instead of doing a @client_teammates.each, you could pluck a list of their salaries, then reduce them into a single sum or, even better, use the sum method provided out-of-the-box by the same API.

sum_of_teammate_salaries_for_client = @client_teammates.sum(:salary)

Your code could therefore look something like this:

@clients.each do |client|
    sum_of_teammate_salaries_for_client = @client_teammates.sum(:salary)
    %li
      %span Profit: #{client.budget - sum_of_teammate_salaries_for_client}
end
Sign up to request clarification or add additional context in comments.

3 Comments

There is probably some ARel/ActiveRecord thingamajig that does the summing in the DB.
Ah, here it is: @client_teammates.sum(:salary) is all you need.
@JörgWMittag thanks for the hint, I'll update the answer. Sheesh, I really ought to grab some RoR project and explore these APIs more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.