Dear RubyReportist''s I''ve been beating up the Rails web forums for the last week trying to understand how ''mature'' Rails web developers'' elect to allow their users to ''mince'' the data. We all know that a normal INDEX action in Rails usually does a Table.find(:all) and there we show the user a list (page by page) of the ''whole show''. Now, what happen''s when the user wants to just see a part of it, or sort by a field, or select a result set a group of separate fields? I''ve seen code like this: def self.search(town, beds, min_price, max_price) conditions = [] conditions << [''town = ?'', town] if town conditions << [''beds = ?'', beds] if beds conditions << [''price >= ?'', min_price] if min_price conditions << [''price <= ?'', max_price] if max_price find(:all, :conditions => [conditions.transpose.first.join('' and ''), *conditions.transpose.last]) But not found anyone that can tie it all together. Are there any people in this group that would be willing to consult to show me a simple example of how this could be done? David Kennedy DauntlessDavid-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org 775-885-9125 --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
On 5/11/07, BraveDave <DauntlessDavid-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Dear RubyReportist''s > I''ve been beating up the Rails web forums for the last week trying to > understand how ''mature'' Rails web developers'' elect to allow their > users to ''mince'' the data. > We all know that a normal INDEX action in Rails usually does a > Table.find(:all) and there we show the user a list (page by page) of > the ''whole show''. > Now, what happen''s when the user wants to just see a part of it, or > sort by a field, or select a result set a group of separate fields? > I''ve seen code like this: > def self.search(town, beds, min_price, max_price) > conditions = [] > conditions << [''town = ?'', town] if town > conditions << [''beds = ?'', beds] if beds > conditions << [''price >= ?'', min_price] if min_price > conditions << [''price <= ?'', max_price] if max_price > find(:all, :conditions => [conditions.transpose.first.join('' and ''), > *conditions.transpose.last]) > But not found anyone that can tie it all together. Are there any > people in this group that would be willing to consult to show me a > simple example of how this could be done?David, First off, I like your approach here, I may implement it myself. But to answer your question as in how I''ve done it. I needed to be able to search within associated tables of has_one, has_many and HABTM all within the same search. I also needed to pass additional filters, that changed the semantics of the search. I have a metaprogramming based approach to this. First, I''ve created a master search class that defines some class level methods and some instance methods like to_conditions, to_includes, to_querystring etc. Each form''s controller derives a subclass from that, assigning fields matching those on the form. E.g. In my controller: class HotelController class HotelSearcher < MasterSearcher attr_accessor :town, :beds, :price # these are accessable to the form end def index hotel_searcher = HotelSearcher.new end def search hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) Hotels.find, :all, :conditions => hotel_seacher.to_conditions # here be majik end In the view, just do a form_for(@hotel_searcher) or use a FormBuilder, etc. To get fancy: class HotelSearcher < MasterSearcher attr_accessor :town, :beds, :price fk_accessor :state, :id, :alias => :state_id ignored :filter, :default => ''all'' end The fk_accessor uses the model and the field to search on. An optional alias can be used for things like id''s in select lists where the options are from a lookup table. (They are all called ''id'' and you can only have one of the same name.) There is an additional #to_includes that gathers the correct include => [] array. The ignored works for form fields that should not participate in the conditions clause, but modify the filter in some way (like order or something else.) You can customize the to_conditions by def to_conditions super do |conditions| # your code goes here end end HTH, Ed> David Kennedy > DauntlessDavid-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > 775-885-9125 > > > > >-- Ed Howland http://greenprogrammer.blogspot.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?hl=en -~----------~----~----~----~------~----~------~--~---
Ed, I feel like I''ve got a tiger by tail here, and am struggling to keep up! I''ve read this post many times and wonder if you''d help me sort it out?>First, I''ve created a master search class that defines some class level methods and some instance methods like to_conditions, to_includes, to_querystring etc. Each form''s controllerderives a subclass from that, assigning fields matching those on the form. What does this ''search class'' inherit from? Is it like a ''login'' table that has no AR backbone? Did you put it in the app/models folder with a name like mother_of_all_query_parameters.rb? What blows me away is that you use the ''form_for'' helper and (from what I''ve read) this supports ONE AR model table? So, if you''ll let me try to tell the story here...it goes like this: Your ''MasterSearcher'' class is designed to hold stuff like query :conditions :filters :sort_by, etc. and is uniquely configured for each ''usage'' by adding the correct attr_accessor fields that are appropriate for the model or combination of models being searched. When the user clicks on SEARCH the search.controller.index action fires and presents the index.rhtml where the user fills in search criteria using the form_for helper. When the user hits the SUBMIT button it fires the SEARCH action that then delivers the search.rhtml to show the user the ''goodies'' they wanted. I can''t see where the @hotel is that you pass to ''feed'' this view? Could you combine your SEARCH action logic into your INDEX logic something like this; def index if the params[:hotel_searcher]) are nil MasterTable.find(:all) else do that voodoo that you do so well end end I''m so new and impressionable to Rails, that I''m striving to be a ''good boy'' and only use the 7 CRUD actions. Thank you, David On May 11, 2:28 pm, "Ed Howland" <ed.howl...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On 5/11/07, BraveDave <DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > > > Dear RubyReportist''s > > I''ve been beating up the Rails web forums for the last week trying to > > understand how ''mature'' Rails web developers'' elect to allow their > > users to ''mince'' the data. > > We all know that a normal INDEX action in Rails usually does a > > Table.find(:all) and there we show the user a list (page by page) of > > the ''whole show''. > > Now, what happen''s when the user wants to just see a part of it, or > > sort by a field, or select a result set a group of separate fields? > > I''ve seen code like this: > > def self.search(town, beds, min_price, max_price) > > conditions = [] > > conditions << [''town = ?'', town] if town > > conditions << [''beds = ?'', beds] if beds > > conditions << [''price >= ?'', min_price] if min_price > > conditions << [''price <= ?'', max_price] if max_price > > find(:all, :conditions => [conditions.transpose.first.join('' and ''), > > *conditions.transpose.last]) > > But not found anyone that can tie it all together. Are there any > > people in this group that would be willing to consult to show me a > > simple example of how this could be done? > > David, > > First off, I like your approach here, I may implement it myself. But > to answer your question as in how I''ve done it. I needed to be able to > search within associated tables of has_one, has_many and HABTM all > within the same search. I also needed to pass additional filters, that > changed the semantics of the search. I have a metaprogramming based > approach to this. First, I''ve created a master search class that > defines some class level methods and some instance methods like > to_conditions, to_includes, to_querystring etc. Each form''s controller > derives a subclass from that, assigning fields matching those on the > form. > > E.g. In my controller: > > class HotelController > class HotelSearcher < MasterSearcher > attr_accessor :town, :beds, :price # these are accessable to the form > end > > def index > hotel_searcher = HotelSearcher.new > end > def search > hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) > Hotels.find, :all, :conditions => hotel_seacher.to_conditions # > here be majik > end > > In the view, just do a form_for(@hotel_searcher) or use a FormBuilder, etc. > > To get fancy: > class HotelSearcher < MasterSearcher > attr_accessor :town, :beds, :price > fk_accessor :state, :id, :alias => :state_id > ignored :filter, :default => ''all'' > end > > The fk_accessor uses the model and the field to search on. An optional > alias can be used for things like id''s in select lists where the > options are from a lookup table. (They are all called ''id'' and you can > only have one of the same name.) There is an additional #to_includes > that gathers the correct include => [] array. > > The ignored works for form fields that should not participate in the > conditions clause, but modify the filter in some way (like order or > something else.) You can customize the to_conditions by > def to_conditions > super do |conditions| > # your code goes here > end > end > > HTH, > Ed > > > David Kennedy > > DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > > 775-885-9125 > > -- > Ed Howlandhttp://greenprogrammer.blogspot.com- Hide quoted text - > > - Show quoted text ---~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
On 5/12/07, BraveDave <DauntlessDavid-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Ed, > I feel like I''ve got a tiger by tail here, and am struggling to keep > up! I''ve read this post many times and wonder if you''d help me sort it > out? > >First, I''ve created a master search class that defines some class level methods and some instance methods like to_conditions, to_includes, to_querystring etc. Each form''s controller > derives a subclass from that, assigning fields matching those on the > form. > > What does this ''search class'' inherit from? Is it like a ''login'' table > that has no AR backbone? Did you put it in the app/models folder with > a name like mother_of_all_query_parameters.rb? What blows me away is > that you use the ''form_for'' helper and (from what I''ve read) this > supports ONE AR model table? >I actually put it in a module in app/helpers called SearchHelper and a class called SearchForm. So in reality my code in the controller looks more like this: class HotelSearcher < SearchHelper::SearchForm. I did it this way to be able to run RSpec tests (which has a convenient spec:helpers Rake task. Also, it is visible to the controller and the view. The form_for doesn''t care about AR. The object just has to be initialized in the controller and respond to method calls for the fields. That''s why I used att_accessor to create them in the class def in the controller.> So, if you''ll let me try to tell the story here...it goes like this: > Your ''MasterSearcher'' class is designed to hold stuff like > query :conditions :filters :sort_by, etc. and is uniquely configured > for each ''usage'' by adding the correct attr_accessor fields that are > appropriate for the model or combination of models being searched.It actually doesn''t hold the sort by but you could do that. The reason I didn''t was because I am using the OpenRico DB grid and it handles (column) sorting via JavaScript and Ajax call backs. I just get the conditions from the derived SearchForm and combine it with the stuff from OpenRico.> When the user clicks on SEARCH the search.controller.index action > fires and presents the index.rhtml where the user fills in search > criteria using the form_for helper. When the user hits the SUBMIT > button it fires the SEARCH action that then delivers the search.rhtml > to show the user the ''goodies'' they wanted. I can''t see where the > @hotel is that you pass to ''feed'' this view? >You are right, my example code was missing that. Should have been: def search hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) @hotels = Hotels.find, :all, :conditions => hotel_seacher.to_conditions # end> Could you combine your SEARCH action logic into your INDEX logic > something like this; > def index > if the params[:hotel_searcher]) are nil > MasterTable.find(:all) > else > do that voodoo that you do so well > end > endYes, that is possible, but not very Railish or RESTful. You should let the router make decisions about which actions to call. Almost all the Rails code I''ve seen has had a form in the index that POSTs to another action. Especially if you do Ajax forms.> I''m so new and impressionable to Rails, that I''m striving to be a > ''good boy'' and only use the 7 CRUD actions.My approach is really REST agnostic. If by 7 you mean (index, new, create, show, edit, update, destroy) only index displays a list of records. Search isn''t usually one of these CRUD things, but something nearly every app I''ve written has needed. In REST you have these two actions: GET /articles and GET /article/123 The first responds with a list, the second with a view of one particular element of that list. Note the the index action has no filter. It is not very modern UI (you''d get back all of the articles of which there could be thousands or more.) How do you filter? How do you page the results? I think Searching and REST are out of each other''s scope. Or it seems that way to me. Alternatively, you could use PragDave''s RADAR approach to architect the app. http://pragdave.pragprog.com/pragdave/2007/03/the_radar_archi.html While not a solution to the search issue, I''ve heard of using this to implement a search in the presentation layer that talks to the back end via REST. Can''t find the URL for it.> Thank you, > DavidSure. Hth, Ed> > > > On May 11, 2:28 pm, "Ed Howland" <ed.howl...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > On 5/11/07, BraveDave <DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > > > > > > > > > > > Dear RubyReportist''s > > > I''ve been beating up the Rails web forums for the last week trying to > > > understand how ''mature'' Rails web developers'' elect to allow their > > > users to ''mince'' the data. > > > We all know that a normal INDEX action in Rails usually does a > > > Table.find(:all) and there we show the user a list (page by page) of > > > the ''whole show''. > > > Now, what happen''s when the user wants to just see a part of it, or > > > sort by a field, or select a result set a group of separate fields? > > > I''ve seen code like this: > > > def self.search(town, beds, min_price, max_price) > > > conditions = [] > > > conditions << [''town = ?'', town] if town > > > conditions << [''beds = ?'', beds] if beds > > > conditions << [''price >= ?'', min_price] if min_price > > > conditions << [''price <= ?'', max_price] if max_price > > > find(:all, :conditions => [conditions.transpose.first.join('' and ''), > > > *conditions.transpose.last]) > > > But not found anyone that can tie it all together. Are there any > > > people in this group that would be willing to consult to show me a > > > simple example of how this could be done? > > > > David, > > > > First off, I like your approach here, I may implement it myself. But > > to answer your question as in how I''ve done it. I needed to be able to > > search within associated tables of has_one, has_many and HABTM all > > within the same search. I also needed to pass additional filters, that > > changed the semantics of the search. I have a metaprogramming based > > approach to this. First, I''ve created a master search class that > > defines some class level methods and some instance methods like > > to_conditions, to_includes, to_querystring etc. Each form''s controller > > derives a subclass from that, assigning fields matching those on the > > form. > > > > E.g. In my controller: > > > > class HotelController > > class HotelSearcher < MasterSearcher > > attr_accessor :town, :beds, :price # these are accessable to the form > > end > > > > def index > > hotel_searcher = HotelSearcher.new > > end > > def search > > hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) > > Hotels.find, :all, :conditions => hotel_seacher.to_conditions # > > here be majik > > end > > > > In the view, just do a form_for(@hotel_searcher) or use a FormBuilder, etc. > > > > To get fancy: > > class HotelSearcher < MasterSearcher > > attr_accessor :town, :beds, :price > > fk_accessor :state, :id, :alias => :state_id > > ignored :filter, :default => ''all'' > > end > > > > The fk_accessor uses the model and the field to search on. An optional > > alias can be used for things like id''s in select lists where the > > options are from a lookup table. (They are all called ''id'' and you can > > only have one of the same name.) There is an additional #to_includes > > that gathers the correct include => [] array. > > > > The ignored works for form fields that should not participate in the > > conditions clause, but modify the filter in some way (like order or > > something else.) You can customize the to_conditions by > > def to_conditions > > super do |conditions| > > # your code goes here > > end > > end > > > > HTH, > > Ed > > > > > David Kennedy > > > DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > > > 775-885-9125 > > > > -- > > Ed Howlandhttp://greenprogrammer.blogspot.com- Hide quoted text - > > > > - Show quoted text - > > > > >-- Ed Howland http://greenprogrammer.blogspot.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?hl=en -~----------~----~----~----~------~----~------~--~---
I''m not sure that this answers your question at all, but there is a nice plugin that helps with searching AR records without the fulltext searching. EZWhere by Ezra, You can start looking at it on his blog at http://brainspl.at/articles/2006/10/03/nested-joins-and-ez-where-update HTH Daniel On 5/14/07, Ed Howland <ed.howland-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > On 5/12/07, BraveDave <DauntlessDavid-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > Ed, > > I feel like I''ve got a tiger by tail here, and am struggling to keep > > up! I''ve read this post many times and wonder if you''d help me sort it > > out? > > >First, I''ve created a master search class that defines some class level > methods and some instance methods like to_conditions, to_includes, > to_querystring etc. Each form''s controller > > derives a subclass from that, assigning fields matching those on the > > form. > > > > What does this ''search class'' inherit from? Is it like a ''login'' table > > that has no AR backbone? Did you put it in the app/models folder with > > a name like mother_of_all_query_parameters.rb? What blows me away is > > that you use the ''form_for'' helper and (from what I''ve read) this > > supports ONE AR model table? > > > > I actually put it in a module in app/helpers called SearchHelper and a > class called SearchForm. So in reality my code in the controller looks > more like this: > class HotelSearcher < SearchHelper::SearchForm. > I did it this way to be able to run RSpec tests (which has a > convenient spec:helpers Rake task. Also, it is visible to the > controller and the view. > > The form_for doesn''t care about AR. The object just has to be > initialized in the controller and respond to method calls for the > fields. That''s why I used att_accessor to create them in the class def > in the controller. > > > So, if you''ll let me try to tell the story here...it goes like this: > > Your ''MasterSearcher'' class is designed to hold stuff like > > query :conditions :filters :sort_by, etc. and is uniquely configured > > for each ''usage'' by adding the correct attr_accessor fields that are > > appropriate for the model or combination of models being searched. > > It actually doesn''t hold the sort by but you could do that. The reason > I didn''t was because I am using the OpenRico DB grid and it handles > (column) sorting via JavaScript and Ajax call backs. I just get the > conditions from the derived SearchForm and combine it with the stuff > from OpenRico. > > > When the user clicks on SEARCH the search.controller.index action > > fires and presents the index.rhtml where the user fills in search > > criteria using the form_for helper. When the user hits the SUBMIT > > button it fires the SEARCH action that then delivers the search.rhtml > > to show the user the ''goodies'' they wanted. I can''t see where the > > @hotel is that you pass to ''feed'' this view? > > > You are right, my example code was missing that. Should have been: > def search > hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) > @hotels = Hotels.find, :all, :conditions => > hotel_seacher.to_conditions # > end > > > Could you combine your SEARCH action logic into your INDEX logic > > something like this; > > def index > > if the params[:hotel_searcher]) are nil > > MasterTable.find(:all) > > else > > do that voodoo that you do so well > > end > > end > > Yes, that is possible, but not very Railish or RESTful. You should let > the router make decisions about which actions to call. Almost all the > Rails code I''ve seen has had a form in the index that POSTs to another > action. Especially if you do Ajax forms. > > > I''m so new and impressionable to Rails, that I''m striving to be a > > ''good boy'' and only use the 7 CRUD actions. > > My approach is really REST agnostic. If by 7 you mean (index, new, > create, show, edit, update, destroy) only index displays a list of > records. Search isn''t usually one of these CRUD things, but something > nearly every app I''ve written has needed. > > In REST you have these two actions: > GET /articles > and > GET /article/123 > The first responds with a list, the second with a view of one > particular element of that list. Note the the index action has no > filter. It is not very modern UI (you''d get back all of the articles > of which there could be thousands or more.) How do you filter? How do > you page the results? > > I think Searching and REST are out of each other''s scope. Or it seems > that way to me. > > Alternatively, you could use PragDave''s RADAR approach to architect the > app. > > http://pragdave.pragprog.com/pragdave/2007/03/the_radar_archi.html > > While not a solution to the search issue, I''ve heard of using this to > implement a search in the presentation layer that talks to the back > end via REST. Can''t find the URL for it. > > > Thank you, > > David > > Sure. > > Hth, > Ed > > > > > > > > > > On May 11, 2:28 pm, "Ed Howland" <ed.howl...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > On 5/11/07, BraveDave <DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > > > > > > > > > > > > > > > > > > > Dear RubyReportist''s > > > > I''ve been beating up the Rails web forums for the last week trying > to > > > > understand how ''mature'' Rails web developers'' elect to allow their > > > > users to ''mince'' the data. > > > > We all know that a normal INDEX action in Rails usually does a > > > > Table.find(:all) and there we show the user a list (page by page) of > > > > the ''whole show''. > > > > Now, what happen''s when the user wants to just see a part of it, or > > > > sort by a field, or select a result set a group of separate fields? > > > > I''ve seen code like this: > > > > def self.search(town, beds, min_price, max_price) > > > > conditions = [] > > > > conditions << [''town = ?'', town] if town > > > > conditions << [''beds = ?'', beds] if beds > > > > conditions << [''price >= ?'', min_price] if min_price > > > > conditions << [''price <= ?'', max_price] if max_price > > > > find(:all, :conditions => [conditions.transpose.first.join('' and > ''), > > > > *conditions.transpose.last]) > > > > But not found anyone that can tie it all together. Are there any > > > > people in this group that would be willing to consult to show me a > > > > simple example of how this could be done? > > > > > > David, > > > > > > First off, I like your approach here, I may implement it myself. But > > > to answer your question as in how I''ve done it. I needed to be able to > > > search within associated tables of has_one, has_many and HABTM all > > > within the same search. I also needed to pass additional filters, that > > > changed the semantics of the search. I have a metaprogramming based > > > approach to this. First, I''ve created a master search class that > > > defines some class level methods and some instance methods like > > > to_conditions, to_includes, to_querystring etc. Each form''s controller > > > derives a subclass from that, assigning fields matching those on the > > > form. > > > > > > E.g. In my controller: > > > > > > class HotelController > > > class HotelSearcher < MasterSearcher > > > attr_accessor :town, :beds, :price # these are accessable to > the form > > > end > > > > > > def index > > > hotel_searcher = HotelSearcher.new > > > end > > > def search > > > hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) > > > Hotels.find, :all, :conditions => hotel_seacher.to_conditions # > > > here be majik > > > end > > > > > > In the view, just do a form_for(@hotel_searcher) or use a FormBuilder, > etc. > > > > > > To get fancy: > > > class HotelSearcher < MasterSearcher > > > attr_accessor :town, :beds, :price > > > fk_accessor :state, :id, :alias => :state_id > > > ignored :filter, :default => ''all'' > > > end > > > > > > The fk_accessor uses the model and the field to search on. An optional > > > alias can be used for things like id''s in select lists where the > > > options are from a lookup table. (They are all called ''id'' and you can > > > only have one of the same name.) There is an additional #to_includes > > > that gathers the correct include => [] array. > > > > > > The ignored works for form fields that should not participate in the > > > conditions clause, but modify the filter in some way (like order or > > > something else.) You can customize the to_conditions by > > > def to_conditions > > > super do |conditions| > > > # your code goes here > > > end > > > end > > > > > > HTH, > > > Ed > > > > > > > David Kennedy > > > > DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > > > > 775-885-9125 > > > > > > -- > > > Ed Howlandhttp://greenprogrammer.blogspot.com- Hide quoted text - > > > > > > - Show quoted text - > > > > > > > > > > > > -- > Ed Howland > http://greenprogrammer.blogspot.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?hl=en -~----------~----~----~----~------~----~------~--~---
On 5/14/07, Daniel N <has.sox-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m not sure that this answers your question at all, but there is a nice > plugin that helps with searching AR records without the fulltext searching. > EZWhere by Ezra, You can start looking at it on his blog at > http://brainspl.at/articles/2006/10/03/nested-joins-and-ez-where-update > > HTH > DanielThis is a nice conditions generator and it handles the nested joins that many I''ve seen lacked. I like the embedding of order by in the syntax. I was trying to solve the first half of the problem (for which this plugin solves the second 1/2 nicely.) IOW, how do you go from a search form to a conditions array? Esp. when you have multiple join tables that participate in the search. In many cases, if you have a single model to search, you can create it in the search index action @model = MyModel.new Then use form_for on @model and then again in the SUBMIT action @model = MyModel.new(params[:model] ... somehow create the conditions array from the fields in the model. ... perhaps via EXWhere above. But how do you make this DRY? It seems that each form is going to have to be handled independently, and this make sense, but I wanted to convert from any form into any conditions array and do it OAOO. My approach to form processing could use an EZWhere plugin internally, because I am using metaprogramming to generate the fields. Ed> > > On 5/14/07, Ed Howland < ed.howland-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > On 5/12/07, BraveDave < DauntlessDavid-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > Ed, > > > I feel like I''ve got a tiger by tail here, and am struggling to keep > > > up! I''ve read this post many times and wonder if you''d help me sort it > > > out? > > > >First, I''ve created a master search class that defines some class level > methods and some instance methods like to_conditions, to_includes, > to_querystring etc. Each form''s controller > > > derives a subclass from that, assigning fields matching those on the > > > form. > > > > > > What does this ''search class'' inherit from? Is it like a ''login'' table > > > that has no AR backbone? Did you put it in the app/models folder with > > > a name like mother_of_all_query_parameters.rb? What > blows me away is > > > that you use the ''form_for'' helper and (from what I''ve read) this > > > supports ONE AR model table? > > > > > > > I actually put it in a module in app/helpers called SearchHelper and a > > class called SearchForm. So in reality my code in the controller looks > > more like this: > > class HotelSearcher < SearchHelper::SearchForm. > > I did it this way to be able to run RSpec tests (which has a > > convenient spec:helpers Rake task. Also, it is visible to the > > controller and the view. > > > > The form_for doesn''t care about AR. The object just has to be > > initialized in the controller and respond to method calls for the > > fields. That''s why I used att_accessor to create them in the class def > > in the controller. > > > > > So, if you''ll let me try to tell the story here...it goes like this: > > > Your ''MasterSearcher'' class is designed to hold stuff like > > > query :conditions :filters :sort_by, etc. and is uniquely configured > > > for each ''usage'' by adding the correct attr_accessor fields that are > > > appropriate for the model or combination of models being searched. > > > > It actually doesn''t hold the sort by but you could do that. The reason > > I didn''t was because I am using the OpenRico DB grid and it handles > > (column) sorting via JavaScript and Ajax call backs. I just get the > > conditions from the derived SearchForm and combine it with the stuff > > from OpenRico. > > > > > When the user clicks on SEARCH the search.controller.index action > > > fires and presents the index.rhtml where the user fills in search > > > criteria using the form_for helper. When the user hits the SUBMIT > > > button it fires the SEARCH action that then delivers the search.rhtml > > > to show the user the ''goodies'' they wanted. I can''t see where the > > > @hotel is that you pass to ''feed'' this view? > > > > > You are right, my example code was missing that. Should have been: > > def search > > hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) > > @hotels = Hotels.find, :all, :conditions => > hotel_seacher.to_conditions # > > end > > > > > Could you combine your SEARCH action logic into your INDEX logic > > > something like this; > > > def index > > > if the params[:hotel_searcher]) are nil > > > MasterTable.find(:all) > > > else > > > do that voodoo that you do so well > > > end > > > end > > > > Yes, that is possible, but not very Railish or RESTful. You should let > > the router make decisions about which actions to call. Almost all the > > Rails code I''ve seen has had a form in the index that POSTs to another > > action. Especially if you do Ajax forms. > > > > > I''m so new and impressionable to Rails, that I''m striving to be a > > > ''good boy'' and only use the 7 CRUD actions. > > > > My approach is really REST agnostic. If by 7 you mean (index, new, > > create, show, edit, update, destroy) only index displays a list of > > records. Search isn''t usually one of these CRUD things, but something > > nearly every app I''ve written has needed. > > > > In REST you have these two actions: > > GET /articles > > and > > GET /article/123 > > The first responds with a list, the second with a view of one > > particular element of that list. Note the the index action has no > > filter. It is not very modern UI (you''d get back all of the articles > > of which there could be thousands or more.) How do you filter? How do > > you page the results? > > > > I think Searching and REST are out of each other''s scope. Or it seems > > that way to me. > > > > Alternatively, you could use PragDave''s RADAR approach to architect the > app. > > > > > http://pragdave.pragprog.com/pragdave/2007/03/the_radar_archi.html > > > > While not a solution to the search issue, I''ve heard of using this to > > implement a search in the presentation layer that talks to the back > > end via REST. Can''t find the URL for it. > > > > > Thank you, > > > David > > > > Sure. > > > > Hth, > > Ed > > > > > > > > > > > > > > > > On May 11, 2:28 pm, "Ed Howland" <ed.howl...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > On 5/11/07, BraveDave < DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Dear RubyReportist''s > > > > > I''ve been beating up the Rails web forums for the last week trying > to > > > > > understand how ''mature'' Rails web developers'' elect to allow their > > > > > users to ''mince'' the data. > > > > > We all know that a normal INDEX action in Rails usually does a > > > > > Table.find(:all) and there we show the user a list (page by page) of > > > > > the ''whole show''. > > > > > Now, what happen''s when the user wants to just see a part of it, or > > > > > sort by a field, or select a result set a group of separate fields? > > > > > I''ve seen code like this: > > > > > def self.search(town, beds, min_price, max_price) > > > > > conditions = [] > > > > > conditions << [''town = ?'', town] if town > > > > > conditions << [''beds = ?'', beds] if beds > > > > > conditions << [''price >= ?'', min_price] if min_price > > > > > conditions << [''price <= ?'', max_price] if max_price > > > > > find(:all, :conditions => [conditions.transpose.first.join('' and > ''), > > > > > *conditions.transpose.last ]) > > > > > But not found anyone that can tie it all together. Are there any > > > > > people in this group that would be willing to consult to show me a > > > > > simple example of how this could be done? > > > > > > > > David, > > > > > > > > First off, I like your approach here, I may implement it myself. But > > > > to answer your question as in how I''ve done it. I needed to be able to > > > > search within associated tables of has_one, has_many and HABTM all > > > > within the same search. I also needed to pass additional filters, that > > > > changed the semantics of the search. I have a metaprogramming based > > > > approach to this. First, I''ve created a master search class that > > > > defines some class level methods and some instance methods like > > > > to_conditions, to_includes, to_querystring etc. Each form''s controller > > > > derives a subclass from that, assigning fields matching those on the > > > > form. > > > > > > > > E.g. In my controller: > > > > > > > > class HotelController > > > > class HotelSearcher < MasterSearcher > > > > attr_accessor :town, :beds, :price # these are accessable to > the form > > > > end > > > > > > > > def index > > > > hotel_searcher = HotelSearcher.new > > > > end > > > > def search > > > > hotel_searcher = HotelSearcher.new(params[:hotel_searcher]) > > > > Hotels.find, :all, :conditions => hotel_seacher.to_conditions # > > > > here be majik > > > > end > > > > > > > > In the view, just do a form_for(@hotel_searcher) or use a FormBuilder, > etc. > > > > > > > > To get fancy: > > > > class HotelSearcher < MasterSearcher > > > > attr_accessor :town, :beds, :price > > > > fk_accessor :state, :id, :alias => :state_id > > > > ignored :filter, :default => ''all'' > > > > end > > > > > > > > The fk_accessor uses the model and the field to search on. An optional > > > > alias can be used for things like id''s in select lists where the > > > > options are from a lookup table. (They are all called ''id'' and you can > > > > only have one of the same name.) There is an additional #to_includes > > > > that gathers the correct include => [] array. > > > > > > > > The ignored works for form fields that should not participate in the > > > > conditions clause, but modify the filter in some way (like order or > > > > something else.) You can customize the to_conditions by > > > > def to_conditions > > > > super do |conditions| > > > > # your code goes here > > > > end > > > > end > > > > > > > > HTH, > > > > Ed > > > > > > > > > David Kennedy > > > > > DauntlessDa...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > > > > > 775-885-9125 > > > > > > > > -- > > > > Ed Howlandhttp://greenprogrammer.blogspot.com- Hide > quoted text - > > > > > > > > - Show quoted text - > > > > > > > > > > > > > > > > > > > -- > > Ed Howland > > http://greenprogrammer.blogspot.com > > > > > > > > >-- Ed Howland http://greenprogrammer.blogspot.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?hl=en -~----------~----~----~----~------~----~------~--~---