Cgi params in ruby


(Cere Davis) #1

Hi Rubiers,

I can’t figure out a way to make the following code do what I want:

#!/usr/bin/ruby1.8 -w

require ‘cgi’

cgi=CGI.new(“html3”)
cgi.out() do
cgi.html() do
cgi.body() do
cgi.form(“get”) do

 cgi.params.to_a.each {|key, val|
     cgi.text_field(key, val.to_s) +
     cgi.br
 } +
 cgi.submit("Okey Dokey?")

 end

end
end
end

So say I post in something this when I run the script on the command line:

(offline mode: enter name=value pairs on standard input)
lname=davis;fname=cere

…/t.cgi:15:in +': cannot convert String into Array (TypeError) from ./t.cgi:15 from ./t.cgi:9:inform’
from ./t.cgi:9
from ./t.cgi:8:in body' from ./t.cgi:8 from ./t.cgi:7:inhtml’
from /usr/lib/ruby/1.8/cgi.rb:1678:in html' from /usr/lib/ruby/1.8/cgi.rb:1678:inhtml’
from ./t.cgi:7
from ./t.cgi:6:in `out’
from ./t.cgi:6

What I want to happen is for the cgi script to print the lname and fname
into two text_field boxes but I am having trouble tracing through this
error. Can anyone help?

Thanks,
Cere


(Armin Roehrl) #2
cgi.params.to_a.each {|key, val|
    cgi.text_field(key, val.to_s) +
    cgi.br
}

-> Array

cgi.submit("Okey Dokey?")

-> String.

Array+String=Problem

e.g. you could store the result from the .each in a string

cgi.body() do
s= ''
cgi.form(“get”) do
cgi.params.to_a.each {|key, val|
s << cgi.text_field(key, val[0].to_s) + cgi.br
}
s+cgi.submit(“Okey Dokey?”)
end
end

hope this is what u wanted,
-Armin


(Mark Hubbart) #3

Hi Rubiers,

I can’t figure out a way to make the following code do what I want:

interestingly enough, I was just working on that same problem this
morning :slight_smile:

It looks like there is one error, and one unecessary complication.
First, you don’t need to convert the cgi.params to an array. You can
use it as a hash just fine. Second, the CGI methods like #text_field
don’t print their result, they return them. So, since you are using
Array#each, the value of the statement is… the array itself.
Instead, you need to use #map and join the results:

#!/usr/bin/ruby1.8 -w

require ‘cgi’

cgi=CGI.new(“html3”)
cgi.out() do
cgi.html() do
cgi.body() do
cgi.form(“get”) do

   # use Hash#map(), which passes keys and values
cgi.params.map {|key, val|
    cgi.text_field(key, val.to_s) +
    cgi.br
}.join + # and join the result before moving on
cgi.submit("Okey Dokey?")

end

end
end
end

So say I post in something this when I run the script on the command
line:

(offline mode: enter name=value pairs on standard input)
lname=davis;fname=cere
Note that you get this error here because #each returns an array, and
you are trying to add a string to it:
…/t.cgi:15:in +': cannot convert String into Array (TypeError) from ./t.cgi:15 from ./t.cgi:9:inform’
from ./t.cgi:9
from ./t.cgi:8:in body' from ./t.cgi:8 from ./t.cgi:7:inhtml’
from /usr/lib/ruby/1.8/cgi.rb:1678:in html' from /usr/lib/ruby/1.8/cgi.rb:1678:inhtml’
from ./t.cgi:7
from ./t.cgi:6:in `out’
from ./t.cgi:6

What I want to happen is for the cgi script to print the lname and
fname into two text_field boxes but I am having trouble tracing
through this error. Can anyone help?

HTH,
Mark

···

On Feb 13, 2004, at 1:14 PM, Cere Davis wrote:


(Cere Davis) #4

Thank you both for helping me with this.

This an error I am doomed to repeat I’m afraid because I understand
Hash.map and join systax (and didn’t think it existed because ri didn’t
list it under the Hash method).

Hash.map would map to an array of key val pairs I suppose…where val
would be an array still. Then text fields get generated with

Then when I .join it’s doing what?

Thanks.

···
  # use Hash#map(), which passes keys and values
cgi.params.map {|key, val|
    cgi.text_field(key, val.to_s) +
    cgi.br
}.join + # and join the result before moving on
cgi.submit("Okey Dokey?")

(Mark Hubbart) #5

First of all, part of the problem you had, I think, is with the (IMHO)
strange syntax that is used in the CGI module. When you call
cgi.h1{“Title”}, or something like it, all it does is wrap it in the
tag, so:

cgi.h1{“Title”} #=> "

Title

"
or:
cgi.h1{“A " + cgi.bold{“Bold”} + " Title”} #=> "

A Bold
Title

It just returns the string you gave it, but wrapped in a tag. So, if
you do this:
cgi.params.map{|key,value| cgi.text_field(key, val.to_s) + cgi.br }

You end up getting an array of strings that each look something like
this:

You finish it up by #joining the strings.
cgi.params.map{|key,value| cgi.text_field(key, val.to_s) + cgi.br }.join

Which gives you a string containing valid html markup, which can be
passed (in a block) to cgi.form{}, etc.
Also, calling aHash.map is functionally the same as calling
aHash.to_a.map: it passes key/value pairs to the block.

Cheers,
Mark

···

On Feb 13, 2004, at 3:20 PM, Cere Davis wrote:

Thank you both for helping me with this.

This an error I am doomed to repeat I’m afraid because I understand
Hash.map and join systax (and didn’t think it existed because ri
didn’t list it under the Hash method).

Hash.map would map to an array of key val pairs I suppose…where val
would be an array still. Then text fields get generated with

Then when I .join it’s doing what?


(Cere Davis) #6

I agree with you about the cgi syntax strangeness. If you want to hand
enter tag syntax you have to someone splice it in the cgi object
instance and this sort of seems like to heavy of a burned to put on the
end user who just wants to write some simple code. Maybe it’s just my
ignorance but I’ve found this package to be pretty inflexible.

related to that actually…

I wanted to just print labels before the text_field statements so that
one can see the title of the text field that they are filling in.

My intuition would be to just do:

 cgi.params.map {|key, val|
cgi.print key +
cgi.print "  :" +
     cgi.text_field(key, val.to_s) +
     cgi.br
 }.join + # and join the result before moving on
 cgi.submit("Okey Dokey?")

But noooo. It fails. Sorry for being a doofus but what am I doing
wrong now?

Thanks for the explanation below BTW. I get it now.

···

First of all, part of the problem you had, I think, is with the (IMHO)
strange syntax that is used in the CGI module. When you call
cgi.h1{“Title”}, or something like it, all it does is wrap it in the
tag, so:

cgi.h1{“Title”} #=> "

Title

"
or:
cgi.h1{“A " + cgi.bold{“Bold”} + " Title”} #=> "

A Bold
Title

It just returns the string you gave it, but wrapped in a tag. So, if you
do this:
cgi.params.map{|key,value| cgi.text_field(key, val.to_s) + cgi.br }

You end up getting an array of strings that each look something like this:

You finish it up by #joining the strings.
cgi.params.map{|key,value| cgi.text_field(key, val.to_s) + cgi.br }.join

Which gives you a string containing valid html markup, which can be
passed (in a block) to cgi.form{}, etc.
Also, calling aHash.map is functionally the same as calling
aHash.to_a.map: it passes key/value pairs to the block.

Cheers,
Mark


(Mark Hubbart) #7

here:

You want the following code block to return a string each time;

it’ll map to an array of strings, which you join at the end into one

string:
cgi.params.map {|key, val|
# cgi.print immediately outputs what you pass it, rather than
# adding it to the string. just stick a string in there:
key + " :" +
cgi.text_field(key, val.to_s) +
cgi.br
}.join + # and join the result before moving on
cgi.submit(“Okey Dokey?”)

And that should do what you want. Everything is a string; the #title
and #text_field are just shortcuts for creating the html tags. They
always take strings and return strings.

Cheers,
Mark

···

On Feb 13, 2004, at 4:44 PM, Cere Davis wrote:

I agree with you about the cgi syntax strangeness. If you want to
hand enter tag syntax you have to someone splice it in the cgi object
instance and this sort of seems like to heavy of a burned to put on
the end user who just wants to write some simple code. Maybe it’s
just my ignorance but I’ve found this package to be pretty inflexible.

related to that actually…

I wanted to just print labels before the text_field statements so that
one can see the title of the text field that they are filling in.