Incompatible changes to cgi.rb in 1.8.0

Hmm, something has changed in CGI which has broken an application - sorry I
didn’t have a chance to test/comment on this before 1.8.0 was released, but
anyway here’s the information now.

@cgi[‘foo’][0] used to return nil if parameter ‘foo’ was not supplied by the
user. It now returns empty string; so does @cgi[‘foo’]

This is a bit of a problem, since I have code which says

if @cgi[‘foo’][0]
… do stuff if parameter ‘foo’ is supplied
end

in lots of places. But in any case, surely “parameter is missing” should be
represented by nil, since the condition “parameter is present but is an
empty string” is different?

The solution I have found is

if @cgi.params[‘foo’][0]

endif

But that seems to be rather against the spirit of the change to the cgi.rb
module, which was supposed to make accessing parameters easier, not more
convoluted…

Cheers,

Brian.

What about:

if @cgi.has_key? ‘foo’
… do stuff
end

Brian Candler B.Candler@pobox.com wrote in message news:20030804170401.A31567@linnet.org

···

Hmm, something has changed in CGI which has broken an application - sorry I
didn’t have a chance to test/comment on this before 1.8.0 was released, but
anyway here’s the information now.

@cgi[‘foo’][0] used to return nil if parameter ‘foo’ was not supplied by the
user. It now returns empty string; so does @cgi[‘foo’]

This is a bit of a problem, since I have code which says

if @cgi[‘foo’][0]
… do stuff if parameter ‘foo’ is supplied
end

in lots of places. But in any case, surely “parameter is missing” should be
represented by nil, since the condition “parameter is present but is an
empty string” is different?

The solution I have found is

if @cgi.params[‘foo’][0]

endif

But that seems to be rather against the spirit of the change to the cgi.rb
module, which was supposed to make accessing parameters easier, not more
convoluted…

Cheers,

Brian.

Thanks for the suggestion; that does work but unfortunately I
over-simplified my example so it’s not directly applicable.

(1) My code passes cgi variables to functions, e.g.

  database_fetch(@cgi['mykey'][0])

That function uses ‘nil’ to mean ‘no parameter provided, fetch the default
row’.

So either I have to change database_fetch to do a “nil_or_empty?” test as
discussed a few weeks ago, or change the code to

  database_fetch(@cgi.params['mykey'][0])

or
database_fetch(@cgi.has_key?(‘mykey’) ? @cgi[‘mykey’] : nil)

(2) My code binds CGI parameters to Amrita templates to preserve state
through hidden variables in HTML pages:

  require 'amrita/template'

  tmpl = Amrita::TemplateText.new <<EOS
    <input id="mykey" type="hidden" name="mykey" value="">
  EOS

  tmpl.expand($stdout, {   
          :mykey => Amrita::a(:value => @cgi['mykey'][0]),
  })

Amrita interprets :value => nil as ‘strip out attribute “value” completely’.
So if the parameter was unset (nil) on entry, it will not be carried forward
in the generated HTML either, and will remain nil when the page is next
loaded. After this change, the HTML always carries forwards a value of
empty-string for mykey.

This change seems very un-Rubylike to me. If I access myhash[‘foo’] then I
expect to get back nil if there is no key ‘foo’. (Having said that, you
can define a hash to have a default value of empty-string)

I checked the source code and found the following example:

value = cgi[‘field_name’] # <== value string for ‘field_name’
# if not ‘field_name’ included, then return “”.

so it does seem this is an intentional change, not a bug.

I would suggest updating doc/NEWS as follows:

: lib/cgi.rb

cgi[name] returns CGI::QueryExtension::Value that wraps string
value, no longer array.
If parameter is not present then an empty string is returned,
rather than nil.

Regards,

Brian.

···

On Tue, Aug 05, 2003 at 07:37:19AM +0900, Dan Doel wrote:

What about:

if @cgi.has_key? ‘foo’
… do stuff
end

I found another set of places where this change breaks things:

   foo( @cgi['bar'][0] || 'default value' )

no longer works, because the left-hand side returns empty string. I am very
happy with the practice of “nil is false, strings (including empty) and
numbers (including zero) are true” but it doesn’t work here any more :frowning:

Still, a global search-replace of
@cgi[
with
@cgi.params[
seems to have done the trick.

Regards,

Brian.