Find based on conditions defined in the model

Hi all,

Does anyone know how to run a find where a condition is based on an attribute specified in an object's model? I have a Payment object, and in its model I have a function called "amount_unapplied". That code is:

  # Return the amount of the payment that has been applied to invoices   def amount_applied     return self.splits.sum(:amount) == nil ? 0 : self.splits.sum(:amount)   end

In one of my controller methods, I have to return all of the Payment records where amount_unapplied > 0. If I specify it as one of the :conditions in a find, such as:

pmts = Payment.find(:all, :conditions => amount_unapplied > 0)

I get an "undefined local variable or method `amount_unapplied'" exception, as there is no actual column called amount_unapplied...

Any ideas? Thanks!

Neal L wrote:

Hi all,

Does anyone know how to run a find where a condition is based on an attribute specified in an object's model? I have a Payment object, and in its model I have a function called "amount_unapplied". That code is:

  # Return the amount of the payment that has been applied to invoices   def amount_applied     return self.splits.sum(:amount) == nil ? 0 : self.splits.sum(:amount)   end

In one of my controller methods, I have to return all of the Payment records where amount_unapplied > 0. If I specify it as one of the :conditions in a find, such as:

pmts = Payment.find(:all, :conditions => amount_unapplied > 0)

I get an "undefined local variable or method `amount_unapplied'" exception, as there is no actual column called amount_unapplied...

Any ideas? Thanks!

You could create a custom method in your model...

def self.unapplied_payments   find(:all).map {|p| [p] if p.amount_unapplied > 0}.delete_if {|x| x.nil?} end

This line finds all payments, uses array.map to step through and keep the ones that meet the condition amount_unapplied > 0, and deletes out the leftover nil values (the ones where amount_unapplied <= 0).

Payment.unapplied_payments now returns a collection of payments where amount_unapplied > 0

This is a starting point. As you can see it makes a full-table select first and then steps through them - not very efficient. You'd definitely want to enhance your custom method to take normal :find options and apply them before the mapping to improve performance.

Option 2 would be to have an "amount_applied" field on your payment table which you keep up-to-date, then do a normal find with :conditions on that field. It's a tradeoff, but here you get to use the power of the database for the filtering.

Cayce, That was a beautiful explanation...I think you have much 'teacher' in you. Where did you find out about the 'delete_if' method? I've never seen it before. Kathleen KathysKode@gmail.com

KathysKode@gmail.com wrote:

Cayce, That was a beautiful explanation...I think you have much 'teacher' in you. Where did you find out about the 'delete_if' method? I've never seen it before. Kathleen KathysKode@gmail.com

On Jun 4, 10:22�pm, Cayce Balara <rails-mailing-l...@andreas-s.net>

"delete_if" is a standard method on the Ruby Array class - don't forget it's all Ruby underneath! :slight_smile:

http://www.ruby-doc.org/core/ for documentation of Ruby classes. Click on "Array" or "String" or "Integer" under Classes and you'll see documentation of all the standard methods.

Glad I could help and I appreciate the kind words.