0

I have a method which takes ID of project and find all payments, do the math and the output is percentage of success (target amount vs collected)

def projectCollectedMoneyPerc(id)
    @project= Project.find(id)
    @collected = Payment.where('project_id = ? and confirmed = true', @project.id)
    @col = @collected.sum(:amount)

    @perc = ((@col.to_f / @project.amount) * 100).round(0)
end

now I need to find projects which have most % success. My idea was to call this method by sort_by but I have no idea how to put ID from collection to this sort

my collection is simple

@projects=Project.where('enabled = true and enddate > ?', Time.now)

thanks

3
  • You should read a good book about Rails! You are definitely missing out the point of has_many, @collected will usually never be nil, etc. Commented Feb 28, 2016 at 11:23
  • I have model where project has_many payments and payment belongs to project, but when I tried to select when there is no payment at all for project it returned nil or am I missing something? Commented Feb 28, 2016 at 11:27
  • right, now I tested it and it works..thanks, I was doing something wrong for the first time Commented Feb 28, 2016 at 11:32

1 Answer 1

2

I would define a method like to following in your model:

# in app/models/project.rb
has_many :payments

def collected_money_percentage
  sum = payments.where(confirmed: true).sum(:amount)
  (100.0 * sum / amount ).round
end

Then you cound use that method like this:

Project.where('enabled = true and enddate > ?', Time.now)
       .sort_by(&:collected_money_percentage)

Please note that this first loads all matching record and then calculations the percentage in memory. It would probably be faster to calculate this values in your database:

Project.joins(:payments)
  .where('enabled = true and enddate > ?', Time.now)
  .group('projects.id')
  .order('SUM(payments.amount) / projects.amount')
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, that first option using custom function works fine.. second option looks it works ok but ordering is wrong I've added there condition to where (and payments.confirmed = true) to work only with confirmed payments but didnt help

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.