# Appending conditions in a model

**URL:** <https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007>\
**Category:** Rails\
**Created:** [May 14, 2009, 10:29pm UTC](https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007 "2009-05-14T22:29:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 14, 2009, 10:29pm UTC](https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007/1 "2009-05-14T22:29:53Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 15, 2009, 6:20pm UTC](https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007/2 "2009-05-15T18:20:37Z")

</div>

On May 14, 4:28 pm, Mike C [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 15, 2009, 7:05pm UTC](https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007/3 "2009-05-15T19:05:18Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 15, 2009, 7:12pm UTC](https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007/4 "2009-05-15T19:12:58Z")

</div>

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 J.

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 15, 2009, 9:51pm UTC](https://www.ruby-forum.com/t/appending-conditions-in-a-model/168007/5 "2009-05-15T21:51:54Z")

</div>

Wow, thanks for that! I’m using thinking sphinx, but the same thing  
applies, right?
