Class: Rack::MatrixParams

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/matrix_params.rb,
lib/rack/matrix_params/version.rb

Constant Summary collapse

VERSION =
'0.0.1'

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ MatrixParams

Returns a new instance of MatrixParams.



25
26
27
# File 'lib/rack/matrix_params.rb', line 25

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Object

This will allow to use ‘matrix’ params in requests, like:

example.com/library;section=nw/books;topic=money;binding=hardcover

Will result in this params matrix:

> params[‘section’] = ‘nw’

> params[‘topic’] = ‘money’

> params[‘binding’] = ‘hardcover’

All HTTP methods are supported, in case of POST they will be passed as a regular <form> parameters.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rack/matrix_params.rb', line 42

def call(env)
  # Copy PATH_INFO to REQUEST_URI if Rack::Test
  env['REQUEST_URI'] = env['PATH_INFO'] if env['rack.test']

  # Split URI to components and then extract ;var=value pairs
  uri_components = env['REQUEST_URI'].split('/')
  matrix_params = {}
  uri_components.each do |component|
   sub_components, value = component.split(/\;(\w+)\=/), nil
  next unless sub_components.first  # Skip subcomponent if it's empty (usually /)
  while param=sub_components.pop do
    if value
      matrix_params[sub_components.first] ||= {}
      matrix_params[sub_components.first].merge!(
        param => value
      )
      value=nil
      next
    else
      value = param
    end
  end
end

  # If request method is POST, simply include matrix params in form_hash
  env['rack.request.form_hash'].merge!(matrix_params) if env['rack.request.form_hash']

  # For other methods it's a way complicated ;-)
  if env['REQUEST_METHOD']!='POST' and not matrix_params.keys.empty?

    # Rewrite current path and query string and strip all matrix params from it
    env['REQUEST_PATH'], env['PATH_INFO'] = env['REQUEST_URI'].gsub(/;([^\/]*)/, '').gsub(/\?(.*)$/, '')
    env['PATH_INFO'] = env['REQUEST_PATH']
    env['QUERY_STRING'] = env['QUERY_STRING'].gsub(/;([^\/]*)/, '').freeze
    
    new_params = matrix_params.collect do |component, params|
      params.collect { |k,v| "#{component}[#{k}]=#{CGI::escape(v.to_s)}" }
    end.flatten

  	# Add matrix params as a regular GET params
  	env['QUERY_STRING'] += '&' if not env['QUERY_STRING'].empty?
  	env['QUERY_STRING'] += "#{new_params.join('&')}"
  end
  @app.call(env)
end