sinatra-browse 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1faa38c99f34fe11336ea7e4beb14b9c6c8c5d44
4
- data.tar.gz: 2d1cc86c5d25a45f8c557202f095f74a9e145325
3
+ metadata.gz: 5bdedea1f30918fa4b4e9e40329b5d36d376e26a
4
+ data.tar.gz: a3f543ea671453b43857a83971491ebc70469aef
5
5
  SHA512:
6
- metadata.gz: 6a68e861b2d04655faa2a459d9246754b526829c1ca4ebfae6ef0c7c2502a7a39583981cdb22b5ec08819aa311f9d460136b96d90f904db964d586d0b0d448b1
7
- data.tar.gz: 740fbf66e097ea5d34c5998ba248df93a09db40948312b9af0659f5f0b47186ad1f314904419ceee38e4434ebe1a4a8418fe35e8f02a237b4b8a0f2fa168fcdc
6
+ metadata.gz: 5d9ca106f1fc4d51484e5985cfa8f6e66ff18a2fd5deedb325010decb99e1d76dbb86925a436fb1b47e4c1f2cedc0c8f1190d75d92dbba9d39db92c7db378ad9
7
+ data.tar.gz: 792cb9ccd3f3103046644bc72eb23aa71de835cb7b1b2af7cc0cd5313a8fa9b4a63c0f3cf4fe56ab8af5f63222548fe833b4684dcffce8095a986c80bce3e66e
data/README.md CHANGED
@@ -40,12 +40,10 @@ The syntax is inspired by the [sinatra-param](https://github.com/mattt/sinatra-p
40
40
 
41
41
  **Browsable API**
42
42
 
43
- Sinatra-browse allows you to surf to your API. This works as documentation and allows you to send requests and see their responses directly in your browser.
43
+ Sinatra-browse automatically adds another route simply called `browse`. Surfing to it will display documentation generated from the parameter definitions.
44
44
 
45
45
  http://<api_ip_address>:<api_port>/browse
46
46
 
47
- *Remark:* This is still work in progress. Right now the page only shows some simple documentation.
48
-
49
47
  ## Parameter types
50
48
 
51
49
  At the time of writing four parameter types are available.
@@ -53,17 +51,43 @@ At the time of writing four parameter types are available.
53
51
  * `:String`
54
52
  * `:Integer`
55
53
  * `:Float`
56
- * `:Boolean` ["1/0", "true/false", "t/f", "yes/no", "y/n"]
54
+ * `:Boolean`
55
+ * `:DateTime`
56
+
57
+ **Remarks:**
58
+
59
+ A `Boolean` parameter will be true for values: `"1"`, `"true"`, `"t"`, `"yes"`, `"y"` and false for values: `"0"`, `"false"`, `"f"`, `"no"`, `"n"`
60
+
61
+ A `DateTime` parameter relies on Ruby's [DateTime#parse](http://www.ruby-doc.org/stdlib-2.2.2/libdoc/date/rdoc/DateTime.html#method-c-parse) method and can thus handle all formats this method can.
62
+
63
+ Examples:
64
+
65
+ 'Sat, 03 Feb 2001 04:05:06 GMT'
66
+ 'Sat, 3 Feb 2001 04:05:06 +0700'
67
+ '2001-02-03T04:05:06+07:00'
68
+ 'H13.02.03T04:05:06+07:00'
69
+ '2014/02/05'
70
+ 'march 2nd'
57
71
 
58
72
  ## Default values
59
73
 
60
- You can set default values in your declarations. These will be used when the parameter in question wasn't provided in the request. You can either set the default value or provide a proc to generate it.
74
+ You can set default values in your declarations. These will be used when the parameter in question wasn't provided in the request. You can either set the default value or provide a proc/lambda to generate it.
61
75
 
62
76
  ```ruby
63
77
  param :media_type, :String, default: "book"
64
78
  param :year, :Integer, default: lambda { Time.now.year }
65
79
  ```
66
80
 
81
+ ## Describing parameters
82
+
83
+ Parameters declarations can have an optional arbitrary discription to be included in the generated documentation.
84
+
85
+ ```ruby
86
+ # Both of these syntaxes will work.
87
+ param :name, :Name, description: "What your mother calls you."
88
+ param :age, :Integer, desc: "The amount of years you've spent on this planet."
89
+ ```
90
+
67
91
  ## Parameter validation
68
92
 
69
93
  You can write some quick validation logic directly in the parameter declaration. If the validation fails, either a standard 400 error will be returned or a custom error block will execute if provided.
@@ -90,6 +114,30 @@ param :small_prime_number, :Integer, in: Prime.take(10)
90
114
  param :order, :String, in: ["ascending", "descending"]
91
115
  ```
92
116
 
117
+ ### Minimum and maximum validation
118
+
119
+ In the case of numeric values like `:Integer`, `:Float` and `:DateTime`, you can specify a minimum and/or maximum value.
120
+
121
+ `min` The parameter must be greater than or equal to this.
122
+
123
+ ```ruby
124
+ param :min_example, :Integer, min: 128
125
+ ```
126
+
127
+ `max` The parameter must be lesser than or equal to this.
128
+
129
+ ```ruby
130
+ param :max_example, :Float, max: 66.666
131
+ ```
132
+
133
+ In the case of `:DateTime`, min/max validators van be defined as either ruby's DateTime class or a String representation that Ruby's [DateTime#parse](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/DateTime.html#method-c-parse) method can handle.
134
+
135
+ ```ruby
136
+ param :string_min, :DateTime, min: '2014/02/05'
137
+ param :date_max, :DateTime, max: DateTime.ordinal(2005,34,4,5,6,'+7')
138
+ ```
139
+
140
+
93
141
  ### String validation
94
142
 
95
143
  The following parameter validators can only be used for parameters of type `:String`.
@@ -2,18 +2,38 @@
2
2
 
3
3
  require 'sinatra/base'
4
4
 
5
- Dir["#{File.dirname(__FILE__)}/browse/*.rb"].each {|f| require f }
6
- Dir["#{File.dirname(__FILE__)}/browse/parameter_types/*.rb"].each do |f|
7
- require f
8
- end
9
-
10
5
  module Sinatra::Browse
6
+ #
7
+ # Load other files
8
+ #
9
+ require_relative 'browse/format'
10
+ require_relative 'browse/parameter_type'
11
+ require_relative 'browse/route'
12
+ require_relative 'browse/validator'
13
+
14
+ module Errors
15
+ require_relative 'browse/errors'
16
+ end
17
+
18
+ module ParameterTypes
19
+ module MinMax
20
+ require_relative 'browse/parameter_types/min_max'
21
+ end
22
+
23
+ require_relative 'browse/parameter_types/boolean'
24
+ require_relative 'browse/parameter_types/date_time'
25
+ require_relative 'browse/parameter_types/float'
26
+ require_relative 'browse/parameter_types/integer'
27
+ require_relative 'browse/parameter_types/string'
28
+ end
29
+
11
30
  #
12
31
  # Main DSL methods
13
32
  #
14
- def param(name, type, options = {})
33
+ def parameter(name, type, options = {})
15
34
  temp_browse_params[name] = options.merge({ type: type })
16
35
  end
36
+ alias :param :parameter
17
37
 
18
38
  def parameter_options(parameter, options)
19
39
  if temp_browse_params[parameter].nil?
@@ -13,6 +13,10 @@
13
13
  <% route.param_declarations.each do |name, param| %>
14
14
  <dt><%= param.name %></dt>
15
15
 
16
+ <% if param.description %>
17
+ <dd><%= param.description %><dd>
18
+ <% end %>
19
+
16
20
  <% if param.required? %>
17
21
  <dd>Required</dd>
18
22
  <% end %>
@@ -1,7 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- module Sinatra::Browse
4
- module Errors
5
- class UnknownParameterError < Exception; end
6
- end
3
+ module Sinatra::Browse::Errors
4
+ class UnknownParameterError < Exception; end
5
+ class UnknownParameterTypeError < Exception; end
7
6
  end
@@ -1,19 +1,34 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Sinatra::Browse
4
- def self.parameter_type(name, &blk)
5
- const_set "#{name}Type", Class.new(ParameterType, &blk)
6
- end
7
-
8
4
  class ParameterType
9
5
  attr_reader :name
10
6
  attr_reader :default
11
7
  attr_reader :validators
8
+ attr_reader :description
9
+
10
+ def self.inherited(subclass)
11
+ subclass.class_eval do
12
+ # Initialize the validator hash
13
+ @validator_declarations ||= {}
14
+
15
+ #
16
+ # Global validators
17
+ #
18
+ validator(:in) { |possible_values| possible_values.member?(@value) }
19
+
20
+ # We need a to_s here because the user should be allowed to define dependencies
21
+ # using symbols while the actual keys of the params hash are strings
22
+ validator(:depends_on) { |dep| @params.has_key?(dep.to_s) }
23
+ end
24
+ end
12
25
 
13
26
  def initialize(name, map)
14
27
  @name = name
15
28
  @default = map.delete(:default)
16
29
 
30
+ @description = map.delete(:description) || map.delete(:desc)
31
+
17
32
  @transform = map.delete(:transform)
18
33
  @transform = @transform.to_proc if @transform
19
34
 
@@ -21,8 +36,9 @@ module Sinatra::Browse
21
36
  @on_error = map.delete(:on_error)
22
37
 
23
38
  @validators = []
39
+
24
40
  map.each do |key, value|
25
- if val_blk = @@validator_declarations[key]
41
+ if val_blk = validator_declarations[key]
26
42
  @validators << Validator.new(
27
43
  name: key,
28
44
  criteria: map[key],
@@ -68,7 +84,7 @@ module Sinatra::Browse
68
84
 
69
85
  def type
70
86
  type_string = self.class.to_s.split("::").last
71
- type_string[0, type_string.size - 4].to_sym
87
+ type_string.to_sym
72
88
  end
73
89
 
74
90
  def to_hash(options = {})
@@ -95,23 +111,17 @@ module Sinatra::Browse
95
111
  # DSL
96
112
  #
97
113
 
98
- def self.coerce(&blk)
99
- define_method(:coerce) { |value| blk.call(value) }
100
- end
101
-
102
114
  def self.validator(name, &blk)
103
- @@validator_declarations ||= {}
115
+ @validator_declarations[name] = blk
116
+ end
104
117
 
105
- @@validator_declarations[name] = blk
118
+ def self.validator_declarations
119
+ @validator_declarations
106
120
  end
107
121
 
108
- #
109
- # Validators
110
- #
122
+ def validator_declarations
123
+ self.class.validator_declarations
124
+ end
111
125
 
112
- # We need a to_s here because the user should be allowed to define dependencies
113
- # using symbols while the actual keys of the params hash are strings
114
- validator(:depends_on) { |dep| @params.has_key?(dep.to_s) }
115
- validator(:in) { |possible_values| possible_values.member?(@value) }
116
126
  end
117
127
  end
@@ -1,18 +1,21 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Sinatra::Browse
4
- parameter_type(:Boolean) do
5
- coerce do |value|
6
- #TODO: Raise error if it's something else
7
- # true and false are included here because they can be set as default
8
- # values even though only strings will come through http requests
9
- case value
10
- when "y", "yes", "t", "true", "1", true
11
- true
12
- when "n", "no", "f", "false", "0", false
13
- false
4
+ module ParameterTypes
5
+
6
+ class Boolean < ParameterType
7
+ def coerce(value)
8
+ #TODO: Raise error if it's something else
9
+ # true and false are included here because they can be set as default
10
+ # values even though only strings will come through http requests
11
+ case value
12
+ when "y", "yes", "t", "true", "1", true
13
+ true
14
+ when "n", "no", "f", "false", "0", false
15
+ false
16
+ end
14
17
  end
15
18
  end
16
- end
17
19
 
20
+ end
18
21
  end
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "date"
4
+
5
+ module Sinatra::Browse
6
+ module ParameterTypes
7
+
8
+ class DateTime < ParameterType
9
+ extend MinMax
10
+
11
+ def initialize(name, map)
12
+ # Allow strings for min and max values
13
+ map[:min] = coerce(map[:min]) if map[:min].is_a?(::String)
14
+ map[:max] = coerce(map[:max]) if map[:max].is_a?(::String)
15
+
16
+ super(name, map)
17
+ end
18
+
19
+ def coerce(value)
20
+ # We add this line because default values also get coerced.
21
+ return value if value.is_a?(::DateTime)
22
+
23
+ ::DateTime.parse(value)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -1,7 +1,15 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Sinatra::Browse
4
- parameter_type(:Float) do
5
- coerce { |value| Float(value) }
4
+ module ParameterTypes
5
+
6
+ class Float < ParameterType
7
+ extend MinMax
8
+
9
+ def coerce(value)
10
+ Float(value)
11
+ end
12
+ end
13
+
6
14
  end
7
15
  end
@@ -1,7 +1,15 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Sinatra::Browse
4
- parameter_type(:Integer) do
5
- coerce { |value| Integer(value) }
4
+ module ParameterTypes
5
+
6
+ class Integer < ParameterType
7
+ extend MinMax
8
+
9
+ def coerce(value)
10
+ Integer(value)
11
+ end
12
+ end
13
+
6
14
  end
7
15
  end
@@ -0,0 +1,14 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Sinatra::Browse
4
+ module ParameterTypes
5
+ # This is a module for parameter types to extend. It will give them the
6
+ # validators defined here.
7
+ module MinMax
8
+ def self.extended(parameter_type)
9
+ parameter_type.validator(:min) { |min| @value >= min }
10
+ parameter_type.validator(:max) { |max| @value <= max }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,13 +1,16 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module Sinatra::Browse
4
+ module ParameterTypes
5
+ class String < ParameterType
6
+ def coerce(value)
7
+ String(value)
8
+ end
4
9
 
5
- parameter_type(:String) do
6
- coerce { |value| String(value) }
7
-
8
- validator(:format) { |regex| !! (@value =~ regex) }
9
- validator(:min_length) { |min_len| @value.length >= min_len }
10
- validator(:max_length) { |max_len| @value.length <= max_len }
10
+ #TODO: raise error when declaring a validator that doesn't exist
11
+ validator(:format) { |regex| !! (@value =~ regex) }
12
+ validator(:min_length) { |min_len| @value.length >= min_len }
13
+ validator(:max_length) { |max_len| @value.length <= max_len }
14
+ end
11
15
  end
12
-
13
16
  end
@@ -77,8 +77,14 @@ module Sinatra::Browse
77
77
 
78
78
  declaration_maps.each do |name, map|
79
79
  type = map.delete(:type)
80
+ type_class = Sinatra::Browse::ParameterTypes.const_get(type)
80
81
 
81
- @param_declarations[name] = Sinatra::Browse.const_get("#{type}Type").new(name, map)
82
+ #TODO: Unit test this error
83
+ unless type_class.is_a?(Class) && type_class.ancestors.member?(ParameterType)
84
+ raise Errors::UnknownParameterTypeError, type_class
85
+ end
86
+
87
+ @param_declarations[name] = type_class.new(name, map)
82
88
  end
83
89
  end
84
90
  end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Sinatra::Browse
4
+ module Validators
5
+ class In < Validator
6
+ class InvalidFormat < Exception; end
7
+ class UnableToCoerce < Exception; end
8
+
9
+ def intialize(parameter_type, criteria)
10
+ if ! criteria.respond_to?(:each)
11
+ raise InvalidFormat, "#{criteria} does not have an .each method. " +
12
+ "Can't be used for 'in'."
13
+ end
14
+
15
+ criteria.map!
16
+
17
+ super(parameter_type, criteria)
18
+ end
19
+
20
+ def _validate
21
+ @criteria.member?(@value)
22
+ end
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-browse
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: '0.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Axsh Co. LTD
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-28 00:00:00.000000000 Z
11
+ date: 2015-06-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parameter declaration framework and browsable API for Sinatra
14
14
  email: dev@axsh.net
@@ -17,16 +17,19 @@ extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
19
  - lib/sinatra/browse.rb
20
- - lib/sinatra/browse/route.rb
21
- - lib/sinatra/browse/errors.rb
22
- - lib/sinatra/browse/erb_templates/html.erb
20
+ - lib/sinatra/browse/format.rb
23
21
  - lib/sinatra/browse/erb_templates/markdown.erb
22
+ - lib/sinatra/browse/erb_templates/html.erb
24
23
  - lib/sinatra/browse/parameter_type.rb
25
- - lib/sinatra/browse/parameter_types/boolean.rb
24
+ - lib/sinatra/browse/errors.rb
25
+ - lib/sinatra/browse/validators/in.rb
26
+ - lib/sinatra/browse/route.rb
27
+ - lib/sinatra/browse/parameter_types/min_max.rb
26
28
  - lib/sinatra/browse/parameter_types/float.rb
27
29
  - lib/sinatra/browse/parameter_types/string.rb
30
+ - lib/sinatra/browse/parameter_types/date_time.rb
28
31
  - lib/sinatra/browse/parameter_types/integer.rb
29
- - lib/sinatra/browse/format.rb
32
+ - lib/sinatra/browse/parameter_types/boolean.rb
30
33
  - lib/sinatra/browse/validator.rb
31
34
  - LICENSE
32
35
  - README.md
@@ -42,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
45
  requirements:
43
46
  - - '>='
44
47
  - !ruby/object:Gem::Version
45
- version: '0'
48
+ version: 1.9.3
46
49
  required_rubygems_version: !ruby/object:Gem::Requirement
47
50
  requirements:
48
51
  - - '>='
@@ -55,3 +58,4 @@ signing_key:
55
58
  specification_version: 4
56
59
  summary: Parameter declaration framework and browsable API for Sinatra
57
60
  test_files: []
61
+ has_rdoc: