Can I use conditions outside of find(...)?

Hi all,

Many apps duplicate logic in SQL and in model methods. This isn’t very
DRY. Can I factor out the conditions somehow, and leverage them in both
places, e.g.:

class Order
PRIORITY_CONDITIONS = “(status = 2 AND total > 100) or total > 1000”

def self.find_priority_orders
self.find(:all, :conditions => PRIORITY_CONDITIONS)
end

def priority?
# Using a fictional ‘meets?’ method which applies conditions
# to an object and returns true or false.
[self].select{|o| o.meets?(PRIORITY_CONDITIONS)}.size == 1
end
end

I know I’ve glossed over the handling of parameterized conditions, but
that’s a solvable problem. Does anyone know of a plugin (or API item I
missed) that supports this?

Thanks,

Brian H.

google for rails query plugins?
Did you want the select line to be done in SQL?

[self].select{|o| o.meets?(PRIORITY_CONDITIONS)}.size == 1

Roger,

Thanks for the response. I might not have been clear about this line:

[self].select{|o| o.meets?(PRIORITY_CONDITIONS)}.size == 1

I should have simply written:

o.meets?(PRIORITY_CONDITIONS)

The ‘meets?’ method is testing a given order against the conditions, for
example:

o = Order.find(1)

Return true if the order meets these conditions

o.meets?("(status = 2 AND total > 100) or total > 1000")

meets? does NOT query the database; it simply evaluates the conditions
against the model at hand. This is, of course, sufficient to test a
single model or query an array of models, due to the implementation of
Array#select.

If non-standard SQL functions are used, meets would fail. Perhaps
vendor-specific ConnectionAdapters might override meets? to accomodate
their vendor-specific SQL syntax.

I was hoping that a plugin of this sort existed. The ‘duplicate logic
in SQL and instance methods’ problem has been around forever.

Thanks!

Roger P. wrote:

google for rails query plugins?
Did you want the select line to be done in SQL?

[self].select{|o| o.meets?(PRIORITY_CONDITIONS)}.size == 1

I see so you’d like to basically be able to re-use code

which you do use:

all_good = collection.accept{|member| member.good?}

and you’d like to use it later.
all_good_from_sql = Collection.find :all, :conditions => SOMETHING

Yeah google for rails query plugins there may be one.
Or you could just stick with SQL only :slight_smile:
-R

Brian H. wrote:

Roger,

Thanks for the response. I might not have been clear about this line:

[self].select{|o| o.meets?(PRIORITY_CONDITIONS)}.size == 1

I should have simply written:

o.meets?(PRIORITY_CONDITIONS)

The ‘meets?’ method is testing a given order against the conditions, for
example:

o = Order.find(1)

Return true if the order meets these conditions

o.meets?("(status = 2 AND total > 100) or total > 1000")

meets? does NOT query the database; it simply evaluates the conditions
against the model at hand. This is, of course, sufficient to test a
single model or query an array of models, due to the implementation of
Array#select.

If non-standard SQL functions are used, meets would fail. Perhaps
vendor-specific ConnectionAdapters might override meets? to accomodate
their vendor-specific SQL syntax.

I was hoping that a plugin of this sort existed. The ‘duplicate logic
in SQL and instance methods’ problem has been around forever.

Thanks!

Roger P. wrote:

google for rails query plugins?
Did you want the select line to be done in SQL?

[self].select{|o| o.meets?(PRIORITY_CONDITIONS)}.size == 1

On Apr 16, 1:48 pm, Brian H. [email protected]
wrote:

I was hoping that a plugin of this sort existed. The ‘duplicate logic
in SQL and instance methods’ problem has been around forever.

Thinking about it for a moment will tell you why. What happens if
your conditions include columns not in your model’s table through a
join, and those relationships are not defined in the ORM (or aren’t
eagerly loaded, or… )? What if a subquery appears (" id IN SELECT
id from …")? Even worse, consider the where clauses where more
complex calculations are made… ruby/rails would have to emulate
precisely the math engine in the database, or make those numerical
queries anyway.

It seems so simple in the obvious case of just testing a tables
attributes, but making it work generically would be all but impossible
and be very tricky to use.

On Apr 16, 1:16 pm, Brian H. [email protected]
wrote:

I know I’ve glossed over the handling of parameterized conditions, but
that’s a solvable problem. Does anyone know of a plugin (or API item I
missed) that supports this?

Not that I know of.

However, you can do something like this:

conds = ["blah blah ? ", some_var]

def meets?(conds)
temp = []; self.find(:all, :conditions => conds[0].app).each{|rec|
temp << rec.id}; temp.index(self.id).nil?
end

or

def meets?(conds)
conds[0] << " and id = ?"
conds << self.id
self.find(:first, :conditions=>conds).nil?
end

It does result in a wasted database call though unless your conditions
are super-complex and you can’t readily check them in-model (for
example, if you need to pull in tons of information from other tables).

Clever N. wrote:

On Apr 16, 1:48 pm, Brian H. [email protected]
wrote:

I was hoping that a plugin of this sort existed. The ‘duplicate logic
in SQL and instance methods’ problem has been around forever.

Thinking about it for a moment will tell you why. What happens if
your conditions include columns not in your model’s table through a
join, and those relationships are not defined in the ORM (or aren’t
eagerly loaded, or… )? What if a subquery appears (" id IN SELECT
id from …")? Even worse, consider the where clauses where more
complex calculations are made… ruby/rails would have to emulate
precisely the math engine in the database, or make those numerical
queries anyway.

It seems so simple in the obvious case of just testing a tables
attributes, but making it work generically would be all but impossible
and be very tricky to use.

Yeah, I knew that it would get tricky when you get to vendor-specific
stuff. I wonder how other frameworks, which have generic query
languages (.NET LINQ, Hibernate HQL, JPA JPQL, etc.), handle this. If I
tried to write a plugin for this, I think I’d just commit to handling a
subset of ANSI SQL functions for the model at hand and raise Exceptions
for any others.

I had considered hitting the DB for one row, as in your ‘meets?’
example, but that precludes running the test on an object that is in a
different state than the database, through either my unsaved changes or
someone else’s changes underneath me.

Thanks for the responses!

Brian

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs