Class: Rack::SI

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

Overview

A Rack middleware for converting params to base SI units

Constant Summary collapse

BASE_UNITS =

These are the base SI units to which measurement params will be converted

[:metre, :metres, :meter, :meters, :litre, :litres, :liter, :liters, :joule, :joules, :gram, :grams, :watt, :watts]
DEFAULT_OPTIONS =
{
  :env => false,
  :basic => false,
  :whitelist => [],
  :blacklist => [],
  :path => []
}
VERSION =
'0.1.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ SI

use Rack::SI my_options



22
23
24
25
26
27
28
# File 'lib/rack/si.rb', line 22

def initialize(app, options = {})
  self.app = app
  self.options = DEFAULT_OPTIONS.merge(options)

  normalize_options
  Herbalist.basic = true if Herbalist.respond_to?(:basic) && options[:basic]
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



8
9
10
# File 'lib/rack/si.rb', line 8

def app
  @app
end

#optionsObject

Returns the value of attribute options.



8
9
10
# File 'lib/rack/si.rb', line 8

def options
  @options
end

Instance Method Details

#blacklisted?(param) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/rack/si.rb', line 101

def blacklisted?(param)
  !options[:blacklist].empty? && options[:blacklist].include?(param)
end

#call(env, options = {}) ⇒ Object

Called on each request



38
39
40
41
42
# File 'lib/rack/si.rb', line 38

def call(env, options = {})
  req = Request.new(env)
  convert_params(env, req) if path_matches?(req)
  app.call(env)
end

#convert_params(env, req) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/rack/si.rb', line 51

def convert_params(env, req)
  if options[:env]
    convert_params_in_hash(env, req)
  else
    convert_params_in_situ(env, req)
  end
end

#convert_params_in_hash(env, req) ⇒ Object

Convert parameters, but put them in a special hash and leave the regular Rack ENV params alone. You can specify the name of the env[] key that stores the params by configuring the app with the :env option



63
64
65
66
67
68
69
# File 'lib/rack/si.rb', line 63

def convert_params_in_hash(env, req)
  params = req.params
  hash_name = options[:env].is_a?(String) ? options[:env] : 'si.params'
  env[hash_name] = params.inject({}) do |hsh, (name, value)|
    herbalize(hsh, name, value)
  end
end

#convert_params_in_situ(env, req) ⇒ Object

Convert parameters “in place” - that is, modify all the params in env so that every other middleware sees the changes



74
75
76
77
78
79
80
81
82
# File 'lib/rack/si.rb', line 74

def convert_params_in_situ(env, req)
  env['si.original_params'] = req.params.dup
  [:GET, :POST].each do |method|
    hsh = req.send(method)
    hsh.each do |name, value|
      herbalize(hsh, name, value)
    end
  end
end

#herbalizable?(param) ⇒ Boolean

Decides if a param should be converted with Herbalist

Returns:

  • (Boolean)


93
94
95
# File 'lib/rack/si.rb', line 93

def herbalizable?(param)
  whitelisted?(param) && !blacklisted?(param)
end

#herbalize(hsh, name, value) ⇒ Object

Convert a parameter with Herbalist



85
86
87
88
89
90
# File 'lib/rack/si.rb', line 85

def herbalize(hsh, name, value)
  if herbalizable?(name) && measurement = Herbalist.parse(value)
    hsh[name] = normalize(measurement)
  end
  hsh
end

#normalize(measurement) ⇒ Object

Convert a param to a base unit using Alchemist’s conversion table



107
108
109
110
111
112
113
114
# File 'lib/rack/si.rb', line 107

def normalize(measurement)
  group_name = Alchemist.conversion_table.keys.find do |k|
    Alchemist.conversion_table[k].include?(measurement.unit_name)
  end
  group = Alchemist.conversion_table[group_name]
  base_unit = BASE_UNITS.find { |u| group.include?(u) }
  measurement.to.send(base_unit).to_s
end

#normalize_optionsObject

Make sure options are in the right format



31
32
33
34
35
# File 'lib/rack/si.rb', line 31

def normalize_options
  self.options[:whitelist] = self.options[:whitelist].map(&:to_s)
  self.options[:blacklist] = self.options[:blacklist].map(&:to_s)
  self.options[:path] = [self.options[:path]] unless self.options[:path].is_a?(Array)
end

#path_matches?(req) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
47
48
49
# File 'lib/rack/si.rb', line 44

def path_matches?(req)
  options[:path].empty? || options[:path].find do |path|
    (path.is_a?(String) && req.path == path) ||
      (path.is_a?(Regexp) && req.path =~ path)
  end
end

#whitelisted?(param) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/rack/si.rb', line 97

def whitelisted?(param)
  options[:whitelist].empty? || options[:whitelist].include?(param)
end