I have a Search Model which contains search data. It looks like this: keywords:string by_user:boolean by_title:boolean ... So basically what I want is, if one of the booleans is true it will search that particular index. So if by_user is true and by_title is true, it will search the database of stories by user and title. If only by_user is true, then it will only search by user. So here''s what I''m planning in the Search Model: def stories find_stories end def find_stories find(:all, :conditions => ??) end I''m confused has to how to make the conditions since it will have to check which booleans are true and then append onto the conditions. How would I do this?
On May 14, 4:28 pm, Mike C <snib...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have a Search Model which contains search data. It looks like this: > > keywords:string > by_user:boolean > by_title:boolean[...]> def find_stories > find(:all, :conditions => ??) > end > > I''m confused has to how to make the conditions since it will have to > check which booleans are true and then append onto the conditions. How > would I do this?Remember, :conditions can take a hash, which means you can do what you want if you get your head out of ActiveRecord for a minute and into Ruby hash-munging. :) So for example: def find_stories(by_user = false, by_title = false) conditions = {} conditions[:user] = ''some criteria'' if by_user conditions[:title] = ''more criteria'' if by_title Story.find(:all, :conditions => conditions.merge(:any => ''other'', :options => ''you want'') end Does that help? Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org
Yeah, that helps a lot. I actually realized that a little bit after posting and looked it up on Google, but this confirms it. Thanks! On May 15, 9:19 am, Marnen Laibow-Koser <mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org> wrote:> On May 14, 4:28 pm, Mike C <snib...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I have a Search Model which contains search data. It looks like this: > > > keywords:string > > by_user:boolean > > by_title:boolean > [...] > > def find_stories > > find(:all, :conditions => ??) > > end > > > I''m confused has to how to make the conditions since it will have to > > check which booleans are true and then append onto the conditions. How > > would I do this? > > Remember, :conditions can take a hash, which means you can do what you > want if you get your head out of ActiveRecord for a minute and into > Ruby hash-munging. :) So for example: > > def find_stories(by_user = false, by_title = false) > conditions = {} > conditions[:user] = ''some criteria'' if by_user > conditions[:title] = ''more criteria'' if by_title > Story.find(:all, :conditions => conditions.merge(:any => > ''other'', :options => ''you want'') > end > > Does that help? > > Best, > -- > Marnen Laibow-Koserhttp://www.marnen.org > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org
You can also use the :symbol interpolation support in conditions, to get code that looks like this: def self.find_stories # add parameters as needed conditions = [''1 = 1''] # default; find complains if conditions is empty conditions << ''title LIKE :search'' if by_title conditions << ''user LIKE :search'' if by_user Story.find(:all, :conditions => [conditions.join('' AND ''), {:search => "%#{keywords}%"}]) end This simple example works for a single search term; extending it to split keywords on spaces and combine terms with '' OR '' (or '' AND '', depending on your interpretation of keywords) is fairly straightforward. If you''re doing more complicated things in your searches, you might also want to try using named scopes instead. Something like: def self.find_stories proxy = Story proxy = proxy.search_by_title(keywords) if by_title proxy = proxy.search_by_user(keywords) if by_user proxy end ...where the scopes are defined on Story thus: class Story < AR::Base named_scope :search_by_title, lambda { |keywords| kws keywords.split(/ /); { :conditions => [kws.map { |k| ''title LIKE ?'' }.join('' AND ''), *(kws.map { |k| "%#{k}%" })] } } end and so on for user, where you can now add options like :joins and/ or :include if user is defined on another table. --Matt Jones On May 14, 3:28 pm, Mike C <snib...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have a Search Model which contains search data. It looks like this: > > keywords:string > by_user:boolean > by_title:boolean > ... > > So basically what I want is, if one of the booleans is true it will > search that particular index. So if by_user is true and by_title is > true, it will search the database of stories by user and title. If > only by_user is true, then it will only search by user. > > So here''s what I''m planning in the Search Model: > > def stories > find_stories > end > > def find_stories > find(:all, :conditions => ??) > end > > I''m confused has to how to make the conditions since it will have to > check which booleans are true and then append onto the conditions. How > would I do this?
Wow, thanks for that! I''m using thinking sphinx, but the same thing applies, right? On May 15, 10:12 am, Matt Jones <al2o...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> You can also use the :symbol interpolation support in conditions, to > get code that looks like this: > > def self.find_stories # add parameters as needed > conditions = [''1 = 1''] # default; find complains if conditions is > empty > conditions << ''title LIKE :search'' if by_title > conditions << ''user LIKE :search'' if by_user > Story.find(:all, :conditions => [conditions.join('' AND ''), {:search > => "%#{keywords}%"}]) > end > > This simple example works for a single search term; extending it to > split keywords on spaces and combine terms with '' OR '' (or '' AND '', > depending on your interpretation of keywords) is fairly > straightforward. > > If you''re doing more complicated things in your searches, you might > also want to try using named scopes instead. Something like: > > def self.find_stories > proxy = Story > proxy = proxy.search_by_title(keywords) if by_title > proxy = proxy.search_by_user(keywords) if by_user > proxy > end > > ...where the scopes are defined on Story thus: > > class Story < AR::Base > named_scope :search_by_title, lambda { |keywords| kws > keywords.split(/ /); { :conditions => [kws.map { |k| ''title > LIKE ?'' }.join('' AND ''), *(kws.map { |k| "%#{k}%" })] } } > > end > > and so on for user, where you can now add options like :joins and/ > or :include if user is defined on another table. > > --Matt Jones > > On May 14, 3:28 pm, Mike C <snib...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I have a Search Model which contains search data. It looks like this: > > > keywords:string > > by_user:boolean > > by_title:boolean > > ... > > > So basically what I want is, if one of the booleans is true it will > > search that particular index. So if by_user is true and by_title is > > true, it will search the database of stories by user and title. If > > only by_user is true, then it will only search by user. > > > So here''s what I''m planning in the Search Model: > > > def stories > > find_stories > > end > > > def find_stories > > find(:all, :conditions => ??) > > end > > > I''m confused has to how to make the conditions since it will have to > > check which booleans are true and then append onto the conditions. How > > would I do this?