On 2002.05.14, Wakou Aoyama <wakou / fsinet.or.jp> wrote:
> Hi,
> 
> class CGI
>   class Param < String
>     def initialize(array)
>       self.replace(array[0].dup)
>       @val = array.dup
>     end
>     def each(*arg, &block)
>       @val.each(*arg, &block)
>     end
>     def [](x)
>       @val[x]
>     end
>   end
> 
>   def initialize(arg)
>     @params = {}
>     arg.each() do |key, val|
>       @params[key] = CGI::Param.new(val)
>     end
>   end
>   def [](key)
>     @params[key]
>   end
> end
> 
> test_arg = {"key1" => ["val1", "val2"], "key2"=>["val1", "val2"]}
> cgi = CGI.new(test_arg)
> p cgi["key1"]            # "val1"
> p cgi["key1"] == "val1"  # true
> p cgi["key1"].to_s       # "val1"
> p cgi["key1"].to_a       # ["val1", "val2"]
> p cgi["key1"].type       # CGI::Param
> p cgi["key1"][0]         # "val1"    backward compatibility ;->
> p cgi["key1"][1]         # "val2"
> 
> How about this?

Wakou,

That's pretty close to what I did.  I didn't know about the
self.replace trick, and I don't see how your Param#to_a knows
to return @val, unless that's how String#to_a is implemented
(how was I supposed to know it returned @val without looking
at the core?).

Here's my code:

  class CGI
    class Param < String
      def initialize(value)
        @array = Array.new
        @array << value
        super(value)
      end
      def <<(value)
        @array << value
      end
      def [](index)
        @array[index]
      end
      def to_a
        @array
      end
      def to_s
        @array[0]
      end
    end
  end

  class CGI
    def initialize(request = nil)
      @params = Hash.new
      if not request.nil? and not request.type == Panoptic::HTTP::Request
        raise TypeError, "no implicit conversion from #{request.type}"
      end
      if not request.nil?
        script, params = request.url.split(/\?/)
        if not params.nil?
          params.split(/\&/).each {
            | pair |
            key, value = pair.split(/=/)
            if @params.has_key? key
              @params[key] << value
            else 
              @params[key] = CGI::Param.new(value)
            end
          }
        end
      end
    end

    def [](index)
      @params[index]
    end
  end

  module HTTP
    class Request
      attr_accessor :method, :url, :protocol
    end
  end
end

and my tests:

require 'test/unit'
require 'panoptic/cgi'

class CGITest < Test::Unit::TestCase
  include Panoptic
  
  def test_new
    cgi = CGI.new
    assert_equal(CGI, cgi.type)
  end

  def test_new_with_string
    assert_raises(TypeError) {
      cgi = CGI.new("junk")
    }
  end

  def test_no_param_values
    request = HTTP::Request.new
    request.method = "GET"
    request.url = "/script"
    request.protocol = "1.0"
    cgi = CGI.new(request)
    assert_equal(NilClass, cgi['foo'].type)
    assert_equal(nil, cgi['foo'], "cgi['foo']")
    assert_equal("", cgi['foo'].to_s, "cgi['foo'].to_s")
    assert_equal([], cgi['foo'].to_a, "cgi['foo'].to_a")
  end

  def test_single_param_value
    request = HTTP::Request.new
    request.method = "GET"
    request.url = "/script?foo=bar"
    request.protocol = "1.0"
    cgi = CGI.new(request)
    assert_equal(CGI::Param, cgi['foo'].type)
    assert_equal("bar", cgi['foo'], "cgi['foo']")
    assert_equal("bar", cgi['foo'].to_s, "cgi['foo'].to_s")
    assert_equal(["bar"], cgi['foo'].to_a, "cgi['foo'].to_a")
  end

  def test_multi_param_values
    request = HTTP::Request.new
    request.method = "GET"
    request.url = "/script?foo=one&foo=two&foo=three"
    request.protocol = "1.0"
    cgi = CGI.new(request)
    assert_equal(CGI::Param, cgi['foo'].type)
    assert_equal("one", cgi['foo'], "cgi['foo']")
    assert_equal("one", cgi['foo'].to_s, "cgi['foo'].to_s")
    assert_equal(["one", "two", "three"], cgi['foo'].to_a, "cgi['foo'].to_a")
  end
end

-- Dossy

-- 
Dossy Shiobara                       mail: dossy / panoptic.com 
Panoptic Computer Network             web: http://www.panoptic.com/ 
  "He realized the fastest way to change is to laugh at your own
    folly -- then you can let go and quickly move on." (p. 70)