Creating a search

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

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.

Secondly, we’re still a nice bunch.

On Sat, Mar 8, 2008 at 9:39 PM, Tom Ha [email protected] 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

On Mar 8, 4:39 am, Tom Ha [email protected] 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?”

On Sat, Mar 8, 2008 at 7:54 PM, William J. [email protected]
wrote:

On Mar 8, 4:39 am, Tom Ha [email protected] 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

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(", ")

On 3/8/08, William J. [email protected] wrote:

On Mar 8, 4:39 am, Tom Ha [email protected] 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/