[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Creating a search

Tom Ha

3/8/2008 10:40:00 AM

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
--
Posted via http://www.ruby-....

2 Answers

Arlen Cuss

3/8/2008 12:14:00 PM

0

[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/rubyon....

Secondly, we're still a nice bunch.

On Sat, Mar 8, 2008 at 9:39 PM, Tom Ha <tom999@gmx.net> 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

Tom Ha

3/8/2008 8:50:00 PM

0

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(", ")
--
Posted via http://www.ruby-....