The first public release of the CriteriaQuery plugin is available. CriteriaQuery is an extension to the ActiveRecord find mechanism. It allows object-oriented construction of queries. In short, it lets you write: Person.query.name_like(''name'').join(''address'').city_like(''city'') instead of Person.find(:all, :conditions=>[''people.name LIKE ? AND addresses.city LIKE ?'', ''name'', ''city''], :include=>[:city]) or Person.query.name_like(''name'').join(''address'').city_like(''city'').join(''state'').name_eq(''state'') instead of Person.find(:all, :conditions=>[''people.name LIKE ? AND addresses.city LIKE ? AND states.name=?'', ''name'', ''city'', ''state''], :include=>[:city=>[:state]]) This becomes increasingly useful for more complex queries, especially if the queries need to be dynamically constructed based on user input (see the README for examples). Criteria Queries support joins across multiple associations, as well as using the same table in multiple joins. Documentation is at: http://www.muermann.org/ruby/criteria_query The plugin is available via svn: .script/plugin install http://3columns.net/rubyplayground/projects/criteria_query/trunk/criteria_query Cheers, Max --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
I think this is totally cool. It will save me hours and hours on a directory tool I am writing. Thanks for the thoughtful design. Paul Max Muermann wrote:> The first public release of the CriteriaQuery plugin is available. > > CriteriaQuery is an extension to the ActiveRecord find mechanism. It > allows object-oriented construction of queries. > > In short, it lets you write: > > Person.query.name_like(''name'').join(''address'').city_like(''city'') > > instead of > > Person.find(:all, :conditions=>[''people.name LIKE ? AND addresses.city > LIKE ?'', ''name'', ''city''], :include=>[:city])... -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
I agree. It looks really useful for a reporting feature I''m about to write. Thanks! -Jonathan. On 9/7/06, Paul Davis <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> > > I think this is totally cool. It will save me hours and hours on a > directory tool I am writing. Thanks for the thoughtful design. > > Paul > > Max Muermann wrote: > > The first public release of the CriteriaQuery plugin is available. > > > > CriteriaQuery is an extension to the ActiveRecord find mechanism. It > > allows object-oriented construction of queries. > > > > In short, it lets you write: > > > > Person.query.name_like(''name'').join(''address'').city_like(''city'') > > > > instead of > > > > Person.find(:all, :conditions=>[''people.name LIKE ? AND addresses.city > > LIKE ?'', ''name'', ''city''], :include=>[:city]) > ... > > -- > Posted via http://www.ruby-forum.com/. > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Max Muermann wrote:> The first public release of the CriteriaQuery plugin is available. > > CriteriaQuery is an extension to the ActiveRecord find mechanism. It > allows object-oriented construction of queries. > > In short, it lets you write: > > Person.query.name_like(''name'').join(''address'').city_like(''city'') > > instead of > > Person.find(:all, :conditions=>[''people.name LIKE ? AND addresses.city > LIKE ?'', ''name'', ''city''], :include=>[:city]) > > or > > Person.query.name_like(''name'').join(''address'').city_like(''city'').join(''state'').name_eq(''state'') > > instead of > > Person.find(:all, :conditions=>[''people.name LIKE ? AND addresses.city > LIKE ? AND states.name=?'', ''name'', ''city'', ''state''], > :include=>[:city=>[:state]]) > > This becomes increasingly useful for more complex queries, especially > if the queries need to be dynamically constructed based on user input > (see the README for examples). > > Criteria Queries support joins across multiple associations, as well > as using the same table in multiple joins. >These comments may be partially biased because we are both doing similar work (ARE finders) and CriteriaQuery. They have *alot* in common, but there are some things about CriteriaQuery that I don''t get. Why all of the method chaining? It seems to make the queries almost as long and unreadable as the original. With the example you gave above I would rather prefer the below since to me it is more readable and there isn''t so much .( ''..'' ). going on. Person.find :all, :conditions=> { :name_like=>''name'', :state=>''MI'' }, :include => [ :address => [:state] ] I like what you are thinking with Conjunction and Disjunction, but I am not a big fan of the terminology. I think I would have to read and reread code that looked like: Person.query.disjunction.first_name_eq(''name'').last_name_eq(''name'') It is shorter then the below, the but the below to me looks easier to read, maybe it is because there is visual separation? Person.find :all, :conditions => { :first_name => ''name'', :last_name => ''name'' } I may just like the whitespace separation over the use of .( ''arg'' ). chained together. What are your thoughts on long queries? Can method chaining do them elegantly? I like what you''re thinking, and it is along the same lines that I am thinking, although we are approaching from different angles. At this point I''m just a curious fellow. Zach Dennis Michigan Ruby Users Group - http://www.gr-ruby.org ARE - http://blogs.mktec.com/zdennis/pages/ARE -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.2 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFE/8B8Myx0fW1d8G0RAu6/AJ9iKEM1rg1oU050MF0So/NG+ia8oQCfXtOn efdI2cBAAuzFHbduJgj0jww=ogVY -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
<snip>> > These comments may be partially biased because we are both doing similar > work (ARE finders) and CriteriaQuery. They have *alot* in common, but > there are some things about CriteriaQuery that I don''t get. > > Why all of the method chaining? It seems to make the queries almost as > long and unreadable as the original. > > With the example you gave above I would rather prefer the below since to > me it is more readable and there isn''t so much .( ''..'' ). going on. > > Person.find :all, > :conditions=> { :name_like=>''name'', :state=>''MI'' }, > :include => [ :address => [:state] ] > > I like what you are thinking with Conjunction and Disjunction, but I am > not a big fan of the terminology. I think I would have to read and > reread code that looked like: > Person.query.disjunction.first_name_eq(''name'').last_name_eq(''name'') > > It is shorter then the below, the but the below to me looks easier to > read, maybe it is because there is visual separation? > Person.find :all, > :conditions => { :first_name => ''name'', :last_name => ''name'' } > > I may just like the whitespace separation over the use of .( ''arg'' ). > chained together. > > What are your thoughts on long queries? Can method chaining do them > elegantly? >The main reasoning behind the notation is to make it very easy to build complex conditional queries easily. The method chaining is not required, it''s really just some syntactic sugar. You can also write the above query as pq = Person.query pq.first_name_eq(''name'') pq.last_name_eq(''last_name'') pq.find For simple queries like this, criteria_query does not offer much of an advantage (although on even the simple queries I looked at, there''s about 30% less code to write). For really complex stuff, you also use the block notation, which is structurally nicer: pq = Person.query pq.first_name_eq(''name'') pq.last_name(''eq) pq.join(''addres'') do |address| address.or do |streets| address.street_1_like(''%street%'') address.street_2_like(''%street%'') end address.city_eq(''Sydney'') address.join(''country'') do |country| country.name_eq(''Australia'') end end It becomes more useful if the conditions are dependant on user input: ... address.or do |streets| address.street_1_like(params[:street]) if params[:street] address.street_2_like(params[:street]) if params[:street] end ... Empty subrestrictions do not generate any sql, so the above is safe. I do quite like the array notation of conditions, but I can''t see how you would model joins and disjunctions easily without messing up the syntax too much - but you may have some ideas about that. I really like the way that criteria_query handles joins. Have you looked at the naming scheme for join aliases in ActiveRecord? That makes it almost impossible to use multiple joins in a conditional query, as the aliases are based on the order in which joins to the same table appear. Say Person has two relationships to city, called lives_in and works_in, and you want to find all people based on user input into two search fields: 1. User has entered values for both cities: Person.find(:all, :conditions=>[''cities.name=? AND works_ins_people=?'', ''lives'', ''works''], :include=>[:lives_in, :works_in]) 1. User has entered values for lives_in: Person.find(:all, :conditions=>[''cities.name=?, ''lives'' ], :include=>[:lives_in]) 1. User has entered values for works_in: Person.find(:all, :conditions=>[''cities.name=?'', ''works''], :include=>[:works_in]) This is an area where the .join() stuff gives a significant advantage. I can see a potential advantage in combining the two approaches and doing something like this: pq = Person.query pq.conditions = [ :first_name_eq=>''name'', :last_name_eq=>''last_name'' ] pq.join(''address'') do |address| address.conditions = [ :street_1_like=>''%street%'', :street_2_like=>''%street%'' ] end The benefit of having one expression per method call lies in the ability to decide for each statement whether to add it to the query or not. In the combined example, you would have to have some conditional statement that pieces together the conditions array first, which defeats the purpose somewhat. Interested in hearing your thoughts. Cheers, Max --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
is Criteria Query no longer maintained? I tried the link at <http://www.muermann.org/ruby/criteria_query> but it gave me a page not found error. On 9/7/06, Max Muermann <ruby-DC/T6mWKptNg9hUCZPvPmw@public.gmane.org> wrote:> > <snip> > > > > These comments may be partially biased because we are both doing similar > > work (ARE finders) and CriteriaQuery. They have *alot* in common, but > > there are some things about CriteriaQuery that I don''t get. > > > > Why all of the method chaining? It seems to make the queries almost as > > long and unreadable as the original. > > > > With the example you gave above I would rather prefer the below since to > > me it is more readable and there isn''t so much .( ''..'' ). going on. > > > > Person.find :all, > > :conditions=> { :name_like=>''name'', :state=>''MI'' }, > > :include => [ :address => [:state] ] > > > > I like what you are thinking with Conjunction and Disjunction, but I am > > not a big fan of the terminology. I think I would have to read and > > reread code that looked like: > > Person.query.disjunction.first_name_eq(''name'').last_name_eq(''name'') > > > > It is shorter then the below, the but the below to me looks easier to > > read, maybe it is because there is visual separation? > > Person.find :all, > > :conditions => { :first_name => ''name'', :last_name => ''name'' } > > > > I may just like the whitespace separation over the use of .( ''arg'' ). > > chained together. > > > > What are your thoughts on long queries? Can method chaining do them > > elegantly? > > > > The main reasoning behind the notation is to make it very easy to > build complex conditional queries easily. The method chaining is not > required, it''s really just some syntactic sugar. You can also write > the above query as > > pq = Person.query > pq.first_name_eq(''name'') > pq.last_name_eq(''last_name'') > pq.find > > For simple queries like this, criteria_query does not offer much of an > advantage (although on even the simple queries I looked at, there''s > about 30% less code to write). > > For really complex stuff, you also use the block notation, which is > structurally nicer: > > pq = Person.query > pq.first_name_eq(''name'') > pq.last_name(''eq) > pq.join(''addres'') do |address| > address.or do |streets| > address.street_1_like(''%street%'') > address.street_2_like(''%street%'') > end > address.city_eq(''Sydney'') > address.join(''country'') do |country| > country.name_eq(''Australia'') > end > end > > It becomes more useful if the conditions are dependant on user input: > > ... > address.or do |streets| > address.street_1_like(params[:street]) if params[:street] > address.street_2_like(params[:street]) if params[:street] > end > ... > > Empty subrestrictions do not generate any sql, so the above is safe. > > I do quite like the array notation of conditions, but I can''t see how > you would model joins and disjunctions easily without messing up the > syntax too much - but you may have some ideas about that. > > I really like the way that criteria_query handles joins. Have you > looked at the naming scheme for join aliases in ActiveRecord? That > makes it almost impossible to use multiple joins in a conditional > query, as the aliases are based on the order in which joins to the > same table appear. > > Say Person has two relationships to city, called lives_in and > works_in, and you want to find all people based on user input into two > search fields: > > 1. User has entered values for both cities: > > Person.find(:all, :conditions=>[''cities.name=? AND > works_ins_people=?'', ''lives'', ''works''], :include=>[:lives_in, > :works_in]) > > 1. User has entered values for lives_in: > > Person.find(:all, :conditions=>[''cities.name=?, ''lives'' ], > :include=>[:lives_in]) > > 1. User has entered values for works_in: > > Person.find(:all, :conditions=>[''cities.name=?'', ''works''], > :include=>[:works_in]) > > This is an area where the .join() stuff gives a significant advantage. > > I can see a potential advantage in combining the two approaches and > doing something like this: > > pq = Person.query > pq.conditions = [ :first_name_eq=>''name'', :last_name_eq=>''last_name'' ] > pq.join(''address'') do |address| > address.conditions = [ :street_1_like=>''%street%'', > :street_2_like=>''%street%'' ] > end > > The benefit of having one expression per method call lies in the > ability to decide for each statement whether to add it to the query or > not. In the combined example, you would have to have some conditional > statement that pieces together the conditions array first, which > defeats the purpose somewhat. > > Interested in hearing your thoughts. > > Cheers, > Max > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---