Skip to content

Instantly share code, notes, and snippets.

@brendano
Created August 16, 2008 00:25
Show Gist options
  • Save brendano/5682 to your computer and use it in GitHub Desktop.
Save brendano/5682 to your computer and use it in GitHub Desktop.
mycgi
require 'cgi'
# trying to make cgi.rb suck a tad bit less.
# the main thing I care about is clean, error-free parameter input.
# brendan o'connor (brenocon@gmail.com)
class MyCGI < CGI
def initialize
super("html3")
@converted_opts = {}
end
def opt name, opts={}
self.class.send :define_method, name.to_sym do
@converted_opts[name.to_sym]
end
# if opts[:default].andand.is_a? Array
@converted_opts[name.to_sym] = get(name, opts)
end
# def method_missing(msg, *args)
# @converted_opts[msg] || get(msg)
# end
def get(k, opts={})
k=k.to_s
if params.keys.include?(k)
type_convert k, params[k][0], opts
else
opts[:default]
end
end
TYPES = [:boolean, :bool, :int, :integer, :string, :double, :float]
FLOAT_RE = /^-?((\d+(\.\d+)?)|(\.\d+))$/
def type_convert(name, value, opts)
# stolen from Trollop, the one true Ruby commandline option parser.
opts[:type] =
case opts[:type]
when :boolean, :bool; :bool
when :int, :integer; :int
when :string; :string
when :double, :float; :float
when Class
case opts[:type].to_s # sigh... there must be a better way to do this
when 'TrueClass', 'FalseClass'; :bool
when 'String'; :string
when 'Integer'; :int
when 'Float'; :float
else
raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'"
end
when nil; nil
else
raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type])
end
type_from_default =
case opts[:default]
when Integer; :int
when Numeric; :float
when TrueClass, FalseClass; :bool
when String; :string
when nil; nil
else
raise ArgumentError, "unsupported argument type '#{opts[:default].class.name}'"
end
raise ArgumentError, ":type specification and default type don't match" if opts[:type] && type_from_default && opts[:type] != type_from_default
# opts[:type] = (opts[:type] || type_from_default || raise("Need :type or :default for every param!"))
opts[:type] = (opts[:type] || type_from_default || :string)
return opts[:default] if value.blank?
case opts[:type]
when :bool
value=='y' ? true :
value=='n' ? false :
raise("option '#{name}' needs a boolean-coercible value, but got #{value.inspect}")
when :int
raise "option '#{name}' needs an integer but got #{value.inspect}" unless value =~ /^\d+$/
value.to_i
when :float
raise CommandlineError, "option '#{name}' needs a floating-point number but got #{value.inspect}" unless value =~ FLOAT_RE
value.to_f
when :string
value.to_s
else raise("oops")
end
end
end
class String
def blank?
self =~ /^\s*$/
end
end
class NilClass
def blank?
true
end
end
def prepp(o)
puts "<pre>"
require 'pp'
begin
puts o.pretty_print_inspect.gsub(">","&gt;").gsub("<","&lt;")
rescue
pp o
end
puts "</pre>"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment