module URI

Constants

KEY_VALUE_SEPARATOR

Public Class Methods

nested_parameters(value, key=nil, hash={}) click to toggle source

We cannot send nested hash as a param in HTTP requests. For example, when we would like to send something like this:

{:key => "value", :nested => {:nest => "value"}}

It would be (or should be) mapped like this:

/url/?key=value&nested=%7B%3Anest%3D%3E%5C%22value%5C%22%7D

Doesn’t look to good ;) However there is a simple way to convert a nested hash into a params acceptable form. We can convert it to a form, that can be mapped into params like this:

/url/?key=value&nested[nest]=value

Here is method to convert any nested hash to a “one level” equivalent:

@author Maciej Mensfeld

# File lib/standard/facets/uri/parameters.rb, line 42
def self.nested_parameters(value, key=nil, hash={})
  case value
  when Hash
    value.each do |k,v|
      akey = key.nil? ? :"#{k}" : :"#{key}[#{k}]"
      nested_parameters(v, akey, hash) 
    end
    out_hash
  when Array
    value.each do |v|
      nested_parameters(v, "#{key}[]", hash)
    end
    hash
  when nil then ''
  else
    hash[key] = value
    hash
  end
  parameters(hash)
end
parameters(hash) click to toggle source

Allows for taking a hash and turning it into URI/CGI params Since 1.8.x does not have ordered hashes the params might not be ordered.

@todo ::parameters needs URI escaping.

@author Matt Kirk

# File lib/standard/facets/uri/parameters.rb, line 13
def self.parameters(hash)
  hash.map do |k,v|
    if v.respond_to?(:join)
      "#{k}=#{v.join(",")}"
    else
      "#{k}=#{v}"
    end
  end.join("&")
end

Public Instance Methods

cgi_escape(string) click to toggle source

CGI escape

# File lib/standard/facets/uri/cgi_escape.rb, line 12
def cgi_escape(string)
  string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
    '%' + $1.unpack('H2' * $1.size).join('%').upcase
  end.tr(' ', '+')
end
cgi_parse(query) click to toggle source
# File lib/standard/facets/uri/cgi_escape.rb, line 30
def cgi_parse(query)
  params = Hash.new([].freeze)

  query.split(/[&;]/n).each do |pairs|
    key, value = pairs.split('=',2).collect{|v| cgi_unescape(v) }
    if params.has_key?(key)
      params[key].push(value)
    else
      params[key] = [value]
    end
  end

  params
end
cgi_unescape(string) click to toggle source
# File lib/standard/facets/uri/cgi_escape.rb, line 21
def cgi_unescape(string)
  string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
    [$1.delete('%')].pack('H*')
  end
end
decode(uri) click to toggle source

Decode the uri components.

# File lib/standard/facets/uri/decode.rb, line 9
def decode(uri)
  ## gmosx: hmm is this needed?
  ## guard against invalid filenames for example pictures with
  ## spaces uploaded by users
  escaped_uri = uri.gsub(/ /, "+")

  if md = URI::REGEXP::REL_URI.match(escaped_uri)
    path = "#{md[5]}#{md[6]}"
    type = File.extname(path)
    query_string = md[7]

    ## real_path = "#{$root_dir}/#{path}"

    parameters = URI.query_to_hash(query_string)
    path.gsub!(/\+/, " ")

    return [path, type, parameters, query_string]
  end

  ## this is usefull for uncovering bugs!
  raise ArgumentError.new("the parameter '#{uri}' is not a valid uri")
end
get_query_string(uri)
Alias for: query_get
query(parameters) click to toggle source

Given a hash with parameter/value pairs construct a standard query string.

URI.hash_to_query(:a => 1, :b => 2)
#=> "a=1;b=2"
# File lib/standard/facets/uri/query.rb, line 23
def query(parameters)
  return '' unless parameters
  pairs = []
  parameters.each do |param, value|
    pairs << "#{param}=#{cgi_escape(value.to_s)}"
  end
  return pairs.join(KEY_VALUE_SEPARATOR)
end
query_chomp(uri) click to toggle source

Removes the query string from a uri.

Returns the chomped uri.

# File lib/standard/facets/uri/query.rb, line 92
def query_chomp(uri)
  return nil unless uri
  query_string = self.get_query_string(uri)
  return uri.dup.chomp("?#{query_string}")
end
query_get(uri) click to toggle source

This method returns the query string of a uri.

@param [String] uri

The uri string.

@return [String]

The query string, or `nil` if no query string.
# File lib/standard/facets/uri/query.rb, line 73
def query_get(uri)
  return nil unless uri
  # gmosx: INVESTIGATE ruby's URI seems to differently handle
  # abs and rel uris.
  if md = URI::REGEXP::ABS_URI.match(uri)
    return md[8]
  elsif md = URI::REGEXP::REL_URI.match(uri)
    return md[7]
  end
  return nil
end
Also aliased as: get_query_string
query_hash(query_string) click to toggle source

Extend the basic query string parser provided by the cgi module. converts single valued params (the most common case) to objects instead of arrays

Returns hash of parameters, contains arrays for multivalued parameters (multiselect, checkboxes , etc).

If no query string is provided (nil or “”) returns an empty hash.

# File lib/standard/facets/uri/query.rb, line 45
def query_hash(query_string)
  return {} unless query_string

  query_parameters = cgi_parse(query_string)

  query_parameters.each { |key, val|
    ## replace the array with an object
    query_parameters[key] = val[0] if 1 == val.length
  }

  ## set default value to nil! cgi sets this to []
  query_parameters.default = nil

  return query_parameters
end
query_update(uri, parameters) click to toggle source

Get a uri and a hash of parameters. Inject the hash values as parameters in the query sting path. Returns the full uri.

uri - the uri to filter (String) parameter - hash of parameters to update

Returns the full updated query string.

@todo Optimize this method.

# File lib/standard/facets/uri/query.rb, line 111
def query_update(uri, parameters)
  query_string = self.query_get(uri)
  rest = uri.dup.gsub(/\?#{query_string}/, "")

  hash = self.query_string_to_hash(query_string)
  hash.update(parameters)
  query_string = self.hash_to_query_string(hash)

  unless query_string.strip.empty?
    return "#{rest}?#{query_string}"
  else
    return rest
  end
end
update_request_uri(request, parameters) click to toggle source

Gets the request uri, injects extra parameters in the query string and returns a new uri. The request object is not modified. There is always a qs string so an extra test is skipped.

TODO: find a better name?

# File lib/standard/facets/uri/query.rb, line 135
def update_request_uri(request, parameters)
  hash = request.parameters.dup()
  hash.update(parameters)

  ## use this in hash_to_query
  query_string = hash.collect { |k, v|
    "#{k}=#{v}"
  }.join(";")

  ## return "#{request.translated_uri}?#{query_string}"
  return "#{request.path}?#{query_string}"
end