Creating a search

T

Tom Ha

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
 
A

Arlen Cuss

[Note: parts of this message were removed to make it a legal post.]

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.

- 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:
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
 
T

Tom Ha

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

William James

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?"
 
T

Todd Benson

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
 
R

Rick DeNatale

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top