# Creating a search

**URL:** <https://www.ruby-forum.com/t/creating-a-search/131338>\
**Category:** Ruby\
**Created:** [March 8, 2008, 11:39am UTC](https://www.ruby-forum.com/t/creating-a-search/131338 "2008-03-08T11:39:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![tharrisx](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/e19adc/32.png) [@tharrisx](https://www.ruby-forum.com/u/tharrisx)\
**Post date:** [March 8, 2008, 11:39am UTC](https://www.ruby-forum.com/t/creating-a-search/131338/1 "2008-03-08T11:39:55Z")

</div>

Hi there,

I just spent a night on the following “problem” and cant’ figure it out  
on my own:

I need to have a search function and thought I could do it like this:

- the search page has a form which takes the search criteria (people  
only fill in the criteria they want to use for the search)
- upon submission of the form, the search criteria goes into  
params[:search] (i.e. params[:search][:firstname],  
params[:search][:lastname], params[:search][:gender], etc.)
- the controller takes the values from params[:search] and should  
generate/write the appropriate “conditions” for the search statement  
“User.find(:all, conditions =\> {…})”
- But since submitting the search page/form with only _some_ (not all)  
fields filled in (or check boxes checked, or radio buttons clicked,  
etc.) would generate some “empty” values in the key/value pairs in  
“params[:search]”, the generated search statement would be wrong because  
for example a condition saying " ‘gender’ =\> nil/empty " could be added.
- So, only key/value pairs which have a value that’s not empty should  
generate the “condition” code.

Question 1: Where is the mistake in my code? If I do it like below, I  
get the error: “odd number list for Hash” (at line: see the comment in  
the code). (Note: in this code I don’t exclude the “empty” values.)

Question 2: How do I exclude key/value pairs with an “empty” value from  
generating a “condition” (that would screw my search statement)?

The code until now looks like this:

def search  
@searchresults = ‘’  
if request.post?  
@searchresults = User.find(:all, :conditions =\> {  
# this should render like: ‘firstname’ =\>  
params[:search][:firstname],  
# and no comma for the last: ‘gender’ =\>  
params[:search][:gender]  
i=0 # \<= I get the error for this line  
params[:search].each do |key, value|  
i+=1  
if i \< params[:search].length  
puts “’”+key+"’"+" =\> params[:search][:"+key+"],"  
else  
puts “’”+key+"’"+" =\> params[:search][:"+key+"]"  
end  
end  
})  
end  
end

I spent so many hours thinking about this that I would be really  
thankful for a working solution!

Kind regards,  
Tom

---

<div class="post-metadata">

**Author:** ![tharrisx](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/e19adc/32.png) [@tharrisx](https://www.ruby-forum.com/u/tharrisx)\
**Post date:** [March 8, 2008, 1:15pm UTC](https://www.ruby-forum.com/t/creating-a-search/131338/2 "2008-03-08T13:15:06Z")

</div>

Hi,

Firstly, I’ll make a note that this is the Ruby mailing list. You  
probably  
won’t get many Rails-specific answers here, as we all-too-often are  
bombarded with requests for help with Rails specifics which most of us  
may  
prefer not to know. Here’s their list address:  
[http://groups.google.com/group/rubyonrails-talk](http://groups.google.com/group/rubyonrails-talk).

Secondly, we’re still a nice bunch.

On Sat, Mar 8, 2008 at 9:39 PM, Tom Ha [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> - But since submitting the search page/form with only _some_ (not all)  
> fields filled in (or check boxes checked, or radio buttons clicked,  
> etc.) would generate some “empty” values in the key/value pairs in  
> “params[:search]”, the generated search statement would be wrong because  
> for example a condition saying " ‘gender’ =\> nil/empty " could be added.
> - So, only key/value pairs which have a value that’s not empty should  
> generate the “condition” code.

> ```
> @searchresults = User.find(:all, :conditions => {
> i=0 # <= I get the error for this line
> 
> ```

Conditions is actually a Hash, or expecting a Hash, and indeed, this  
syntax  
is trying to construct a hash. Instead, it looks like you’re writing a  
block  
instead - which can’t work.  
Here’s something to think about:

> > {:a =\> nil, :b =\> 42}.reject {|k,v| v.nil?}  
> > =\> {:b=\>42}

Hash#reject takes a block, returning a new hash, excluding the values  
for  
which the block returned true. (i.e. true, since we say yes to  
`rejecting’)  
It looks like you tried to embed a function/set of methods into the hash  
above (:conditions =\> {stmt; stmt;…}), but we can’t do that. Instead,  
try  
something more functional:  
params[:search].reject {|key, val| val.nil?}.map {|k, v|  
“#{key.inspect}  
=\> #{value.inspect}”}.join(", ")  
This does pretty much everything you try to do here with the loop, and  
it’s  
a bit more concise. Here’s how to read it:

params[:search].reject {|key, val| val.nil?}  
This returns a new hash without any key/val-pair where the value is  
`nil'. Replace `val.nil?’ with your own condition that returns `true' when you don't that value. .map {|k, v| "#{key.inspect} => #{value.inspect}"} This goes through each key/val-pair in the hash, and returns an array. Here's an example of the output: >> {:a => nil, :b => 42}.map {|k,v| "#{k.inspect} => #{v.inspect}"} => [":b => 42", ":a => nil"] >> .join(", ") This does what your loop was trying to do, though slightly more concisely. Array#join takes one argument and uses that as the `separator’,  
stringing  
the elements together with that between.  
\>\> [“:b =\> 42”, “:a =\> nil”].join ", "  
=\> “:b =\> 42, :a =\> nil”  
\>\>

Hope this helps.

Arlen

---

<div class="post-metadata">

**Author:** ![tharrisx](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/e19adc/32.png) [@tharrisx](https://www.ruby-forum.com/u/tharrisx)\
**Post date:** [March 9, 2008, 2:55am UTC](https://www.ruby-forum.com/t/creating-a-search/131338/3 "2008-03-09T02:55:31Z")

</div>

On Mar 8, 4:39 am, Tom Ha [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> params[:search] (i.e. params[:search][:firstname],  
> params[:search][:lastname], params[:search][:gender], etc.)

It is mindless to ask a person “What is your gender?”  
Gender only applies to words.  
The correct question is “What is your sex?”

---

<div class="post-metadata">

**Author:** ![tharrisx](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/e19adc/32.png) [@tharrisx](https://www.ruby-forum.com/u/tharrisx)\
**Post date:** [March 9, 2008, 3:38am UTC](https://www.ruby-forum.com/t/creating-a-search/131338/4 "2008-03-09T03:38:53Z")

</div>

On Sat, Mar 8, 2008 at 7:54 PM, William J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> On Mar 8, 4:39 am, Tom Ha [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > params[:search] (i.e. params[:search][:firstname],  
> > params[:search][:lastname], params[:search][:gender], etc.)
> 
> It is mindless to ask a person “What is your gender?”  
> Gender only applies to words.

I like the idiosyncrasies of language, so I beg to differ on that one.  
Gender only applies to “traits”.

> The correct question is “What is your sex?”

I could use your argument to disagree with that, but I won’t, because  
that is probably the most understandable.

Todd

---

<div class="post-metadata">

**Author:** ![tharrisx](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/e19adc/32.png) [@tharrisx](https://www.ruby-forum.com/u/tharrisx)\
**Post date:** [March 8, 2008, 9:49pm UTC](https://www.ruby-forum.com/t/creating-a-search/131338/5 "2008-03-08T21:49:51Z")

</div>

Thanks a lot for your help, Arlen!

(Actually, the error “odd number list for Hash” still appears (for your  
line of code) but I just learned some very useful things. I think the  
problem is that I can’t just write this code into the place where the  
conditions should appear. I tried putting this new code into an  
eval("…") statement, but it didn’t change anything for the error.  
Well, I’ll follow your advice and ask the other group, then.)

> Instead, try something more functional:  
> params[:search].reject {|key, val| val.nil?}.map {|k, v| “#{k.inspect} =\> #{v.inspect}”}.join(", ")

---

<div class="post-metadata">

**Author:** ![tharrisx](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/e19adc/32.png) [@tharrisx](https://www.ruby-forum.com/u/tharrisx)\
**Post date:** [March 9, 2008, 4:11am UTC](https://www.ruby-forum.com/t/creating-a-search/131338/6 "2008-03-09T04:11:44Z")

</div>

On 3/8/08, William J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Mar 8, 4:39 am, Tom Ha [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > params[:search] (i.e. params[:search][:firstname],  
> > params[:search][:lastname], params[:search][:gender], etc.)
> 
> It is mindless to ask a person “What is your gender?”  
> Gender only applies to words.  
> The correct question is “What is your sex?”

From the Mac Dictionary app:

gender

noun  
See sex sense 3.  
USAGE NOTE  
The word gender has been used since the fourteenth century primarily  
as a grammatical term, referring to the classes of noun in Latin,  
Greek, German, and other languages designated as masculine, feminine,  
or neuter. It has also been used since the fourteenth century in the  
sense ‘the state of being male or female,’ but this did not become a  
common standard use until the mid twentieth century. Although the  
words gender and sex both have the sense ‘the state of being male or  
female,’ they are typically used in slightly different ways: sex tends  
to refer to biological differences, while gender tends to refer to  
cultural or social ones.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
