haveapi 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +12 -0
  3. data/Gemfile +10 -10
  4. data/README.md +19 -12
  5. data/Rakefile +23 -0
  6. data/doc/hooks.erb +35 -0
  7. data/doc/index.md +1 -0
  8. data/doc/json-schema.erb +369 -0
  9. data/doc/protocol.md +178 -38
  10. data/doc/protocol.plantuml +220 -0
  11. data/haveapi.gemspec +6 -10
  12. data/lib/haveapi/action.rb +35 -6
  13. data/lib/haveapi/api.rb +22 -5
  14. data/lib/haveapi/common.rb +7 -0
  15. data/lib/haveapi/exceptions.rb +7 -0
  16. data/lib/haveapi/hooks.rb +19 -8
  17. data/lib/haveapi/model_adapters/active_record.rb +58 -19
  18. data/lib/haveapi/output_formatter.rb +8 -5
  19. data/lib/haveapi/output_formatters/json.rb +6 -1
  20. data/lib/haveapi/params/param.rb +33 -39
  21. data/lib/haveapi/params/resource.rb +20 -0
  22. data/lib/haveapi/params.rb +26 -4
  23. data/lib/haveapi/public/doc/protocol.png +0 -0
  24. data/lib/haveapi/resource.rb +2 -7
  25. data/lib/haveapi/server.rb +87 -26
  26. data/lib/haveapi/tasks/hooks.rb +3 -0
  27. data/lib/haveapi/tasks/yard.rb +12 -0
  28. data/lib/haveapi/validator.rb +134 -0
  29. data/lib/haveapi/validator_chain.rb +99 -0
  30. data/lib/haveapi/validators/acceptance.rb +38 -0
  31. data/lib/haveapi/validators/confirmation.rb +46 -0
  32. data/lib/haveapi/validators/custom.rb +21 -0
  33. data/lib/haveapi/validators/exclusion.rb +38 -0
  34. data/lib/haveapi/validators/format.rb +42 -0
  35. data/lib/haveapi/validators/inclusion.rb +42 -0
  36. data/lib/haveapi/validators/length.rb +71 -0
  37. data/lib/haveapi/validators/numericality.rb +104 -0
  38. data/lib/haveapi/validators/presence.rb +40 -0
  39. data/lib/haveapi/version.rb +2 -1
  40. data/lib/haveapi/views/doc_sidebars/json-schema.erb +7 -0
  41. data/lib/haveapi/views/main_layout.erb +11 -0
  42. data/lib/haveapi/views/version_page.erb +26 -3
  43. data/lib/haveapi.rb +7 -4
  44. metadata +45 -66
@@ -0,0 +1,71 @@
1
+ module HaveAPI
2
+ # Checks the length of a string. It does not have a short form.
3
+ #
4
+ # Full form:
5
+ # string :param, length: {
6
+ # min: 3,
7
+ # max: 10
8
+ # message: 'the error message'
9
+ # }
10
+ #
11
+ # string :param, length: {
12
+ # equals: 8
13
+ # }
14
+ class Validators::Length < Validator
15
+ name :length
16
+ takes :length
17
+
18
+ def setup
19
+ @min = take(:min)
20
+ @max = take(:max)
21
+ @equals = take(:equals)
22
+
23
+ if (@min || @max) && @equals
24
+ fail 'cannot mix min/max with equals'
25
+
26
+ elsif !@min && !@max && !@equals
27
+ fail 'must use either min, max or equals'
28
+ end
29
+
30
+ msg = if @equals
31
+ "length has to be #{@equals}"
32
+
33
+ elsif @min && !@max
34
+ "length has to be minimally #{@min}"
35
+
36
+ elsif !@min && @max
37
+ "length has to be maximally #{@max}"
38
+
39
+ else
40
+ "length has to be in range <#{@min}, #{@max}>"
41
+ end
42
+
43
+ @message = take(:message, msg)
44
+ end
45
+
46
+ def describe
47
+ ret = {
48
+ message: @message,
49
+ }
50
+
51
+ if @equals
52
+ ret[:equals] = @equals
53
+
54
+ else
55
+ ret[:min] = @min if @min
56
+ ret[:max] = @max if @max
57
+ end
58
+
59
+ ret
60
+ end
61
+
62
+ def valid?(v)
63
+ len = v.length
64
+
65
+ return len == @equals if @equals
66
+ return len >= @min if @min && !@max
67
+ return len <= @max if !@min && @max
68
+ len >= @min && len <= @max
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,104 @@
1
+ module HaveAPI
2
+ # Checks the value is a number or a string containing only digits.
3
+ #
4
+ # Full form:
5
+ # string :param, number: {
6
+ # min: 3,
7
+ # max: 10,
8
+ # step: 2,
9
+ # message: 'the error message'
10
+ # }
11
+ #
12
+ # Will allow values +3+, +5+, +7+ and +9+.
13
+ #
14
+ # string :param, number: {
15
+ # min: 3,
16
+ # max: 10,
17
+ # mod: 2,
18
+ # }
19
+ #
20
+ # Will allow values +4+, +6+, +8+ and +10+.
21
+ class Validators::Numericality < Validator
22
+ name :number
23
+ takes :number
24
+
25
+ def setup
26
+ @min = take(:min)
27
+ @max = take(:max)
28
+ @step = take(:step)
29
+ @mod = take(:mod)
30
+ @even = take(:even)
31
+ @odd = take(:odd)
32
+
33
+ msg = if @min && !@max
34
+ "has to be minimally #{@min}"
35
+
36
+ elsif !@min && @max
37
+ "has to be maximally #{@max}"
38
+
39
+ elsif @min && @max
40
+ "has to be in range <#{@min}, #{@max}>"
41
+
42
+ else
43
+ 'has to be a number'
44
+ end
45
+
46
+ if @step
47
+ msg += '; ' unless msg.empty?
48
+ msg += "in steps of #{@step}"
49
+ end
50
+
51
+ if @mod
52
+ msg += '; ' unless msg.empty?
53
+ msg += "mod #{@step} must equal zero"
54
+ end
55
+
56
+ if @odd
57
+ msg += '; ' unless msg.empty?
58
+ msg += "odd"
59
+ end
60
+
61
+ if @even
62
+ msg += '; ' unless msg.empty?
63
+ msg += "even"
64
+ end
65
+
66
+ if @odd && @even
67
+ fail 'cannot be both odd and even at the same time'
68
+ end
69
+
70
+ @message = take(:message, msg)
71
+ end
72
+
73
+ def describe
74
+ ret = {
75
+ message: @message,
76
+ }
77
+
78
+ ret[:min] = @min if @min
79
+ ret[:max] = @max if @max
80
+ ret[:step] = @step if @step
81
+ ret[:mod] = @mod if @mod
82
+ ret[:odd] = @odd if @odd
83
+ ret[:even] = @even if @even
84
+
85
+ ret
86
+ end
87
+
88
+ def valid?(v)
89
+ if v.is_a?(::String)
90
+ return false if /\A\d+\z/ !~ v
91
+ v = v.to_i
92
+ end
93
+
94
+ ret = true
95
+ ret = false if @min && v < @min
96
+ ret = false if @max && v > @max
97
+ ret = false if @step && (v - (@min || 0)) % @step != 0
98
+ ret = false if @mod && v % @mod != 0
99
+ ret = false if @odd && v % 2 == 0
100
+ ret = false if @even && v % 2 > 0
101
+ ret
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,40 @@
1
+ module HaveAPI
2
+ # Checks the value is a number or a string containing only digits.
3
+ #
4
+ # Short form:
5
+ # string :param, required: true
6
+ #
7
+ # Full form:
8
+ # string :param, required: {
9
+ # empty: true/false,
10
+ # message: 'the error message'
11
+ # }
12
+ class Validators::Presence < Validator
13
+ name :present
14
+ takes :required, :present
15
+
16
+ def setup
17
+ return useless if simple? && !take
18
+
19
+ @empty = take(:empty, false)
20
+ @message = take(
21
+ :message,
22
+ @empty ? 'must be present' : 'must be present and non-empty'
23
+ )
24
+ end
25
+
26
+ def describe
27
+ {
28
+ empty: @empty,
29
+ message: @message,
30
+ }
31
+ end
32
+
33
+ def valid?(v)
34
+ return false if v.nil?
35
+ return !v.strip.empty? if !@empty && v.is_a?(::String)
36
+ # FIXME: other data types?
37
+ true
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,4 @@
1
1
  module HaveAPI
2
- VERSION = '0.3.2'
2
+ PROTOCOL_VERSION = '1.0'
3
+ VERSION = '0.4.0'
3
4
  end
@@ -0,0 +1,7 @@
1
+ <h1>Contents</h1>
2
+ <ul class="top-level">
3
+ <li><a href="#envelope">Envelope</a></li>
4
+ <li><a href="#all">OPTIONS /</a></li>
5
+ <li><a href="#versions">OPTIONS /?describe=versions</a></li>
6
+ <li><a href="#default">OPTIONS /?describe=default</a></li>
7
+ </ul>
@@ -34,6 +34,17 @@
34
34
  .table-of-contents li.active > a {
35
35
  font-weight: bold;
36
36
  }
37
+ dl {
38
+ border: 1px solid #ccc;
39
+ }
40
+ dl dt {
41
+ background: #ddd none repeat scroll 0% 0%;
42
+ padding-left: 5px;
43
+ }
44
+ dl dd {
45
+ padding: 5px 0px;
46
+ margin-left: 18px;
47
+ }
37
48
  </style>
38
49
  </head>
39
50
  <body data-spy="scroll" data-target=".table-of-contents">
@@ -1,3 +1,26 @@
1
+ <%
2
+ def format_param_type(param)
3
+ return param[:type] if param[:type] != 'Resource'
4
+ "<a href=\"#root-#{param[:resource].join('-')}-show\">#{param[:type]}</a>"
5
+ end
6
+
7
+ def format_validators(validators)
8
+ ret = ''
9
+ return ret if validators.nil?
10
+
11
+ validators.each do |name, opts|
12
+ ret += "<h5>#{name.to_s.capitalize}</h5>"
13
+ ret += '<dl>'
14
+ opts.each do |k, v|
15
+ ret += "<dt>#{k}</dt><dd>#{v}</dd>"
16
+ end
17
+ ret += '</dl>'
18
+ end
19
+
20
+ ret
21
+ end
22
+ %>
23
+
1
24
  <% def render_resource_body(resource, info, prefix='root', name=nil) %>
2
25
  <% name ||= resource.humanize %>
3
26
  <h2 class="resource" id="<%= "#{prefix}-#{resource}" %>"><%= resource.humanize %></h2>
@@ -46,8 +69,8 @@
46
69
  <td><%= info[:label] %></td>
47
70
  <td><%= param %></td>
48
71
  <td><%= info[:required] ? 'yes' : 'no' %></td>
49
- <td><%= info[:type] %></td>
50
- <td><%= info[:validators] %></td>
72
+ <td><%= format_param_type(info) %></td>
73
+ <td><%= format_validators(info[:validators]) %></td>
51
74
  <td><%= info[:default] == :_nil ? '' : info[:default] %></td>
52
75
  <td><%= info[:description] %></td>
53
76
  </tr>
@@ -79,7 +102,7 @@
79
102
  <tr>
80
103
  <td><%= info[:label] %></td>
81
104
  <td><%= param %></td>
82
- <td><%= info[:type] %></td>
105
+ <td><%= format_param_type(info) %></td>
83
106
  <td><%= info[:description] %></td>
84
107
  </tr>
85
108
  <% end %>
data/lib/haveapi.rb CHANGED
@@ -1,7 +1,9 @@
1
+ ar = defined?(:ActiveRecord)
2
+
1
3
  require 'require_all'
2
- require 'active_record'
4
+ require 'active_record' if ar
3
5
  require 'sinatra/base'
4
- require 'sinatra/activerecord'
6
+ require 'sinatra/activerecord' if ar
5
7
  require 'pp'
6
8
  require 'github/markdown'
7
9
 
@@ -13,10 +15,11 @@ end
13
15
  require_relative 'haveapi/params'
14
16
  require_rel 'haveapi/params/'
15
17
  require_rel 'haveapi/*.rb'
16
- require_rel 'haveapi/model_adapters/'
18
+ require_rel 'haveapi/model_adapters/hash'
19
+ require_rel 'haveapi/model_adapters/active_record' if ar
17
20
  require_rel 'haveapi/authentication'
18
21
  require_rel 'haveapi/actions/*.rb'
19
22
  require_rel 'haveapi/output_formatters/base.rb'
20
23
  require_rel 'haveapi/output_formatters/'
24
+ require_rel 'haveapi/validators/'
21
25
  require_rel 'haveapi/extensions'
22
-
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-13 00:00:00.000000000 Z
11
+ date: 2016-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activerecord
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: 4.1.6
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: 4.1.6
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: require_all
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -56,44 +42,44 @@ dependencies:
56
42
  name: sinatra
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - '>='
45
+ - - ~>
60
46
  - !ruby/object:Gem::Version
61
- version: '0'
47
+ version: 1.4.6
62
48
  type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - '>='
52
+ - - ~>
67
53
  - !ruby/object:Gem::Version
68
- version: '0'
54
+ version: 1.4.6
69
55
  - !ruby/object:Gem::Dependency
70
- name: mysql
56
+ name: tilt
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - '>='
59
+ - - ~>
74
60
  - !ruby/object:Gem::Version
75
- version: '0'
61
+ version: 1.4.1
76
62
  type: :runtime
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - '>='
66
+ - - ~>
81
67
  - !ruby/object:Gem::Version
82
- version: '0'
68
+ version: 1.4.1
83
69
  - !ruby/object:Gem::Dependency
84
- name: sinatra-activerecord
70
+ name: redcarpet
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - '>='
73
+ - - ~>
88
74
  - !ruby/object:Gem::Version
89
- version: '0'
75
+ version: 3.3.4
90
76
  type: :runtime
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
- - - '>='
80
+ - - ~>
95
81
  - !ruby/object:Gem::Version
96
- version: '0'
82
+ version: 3.3.4
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rake
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -114,56 +100,28 @@ dependencies:
114
100
  requirements:
115
101
  - - ~>
116
102
  - !ruby/object:Gem::Version
117
- version: 0.6.6
103
+ version: 0.6.9
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - ~>
123
109
  - !ruby/object:Gem::Version
124
- version: 0.6.6
125
- - !ruby/object:Gem::Dependency
126
- name: rspec
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - '>='
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - '>='
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: railties
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - '>='
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - '>='
151
- - !ruby/object:Gem::Version
152
- version: '0'
110
+ version: 0.6.9
153
111
  - !ruby/object:Gem::Dependency
154
- name: rack-test
112
+ name: nesty
155
113
  requirement: !ruby/object:Gem::Requirement
156
114
  requirements:
157
- - - '>='
115
+ - - ~>
158
116
  - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
117
+ version: 1.0.2
118
+ type: :runtime
161
119
  prerelease: false
162
120
  version_requirements: !ruby/object:Gem::Requirement
163
121
  requirements:
164
- - - '>='
122
+ - - ~>
165
123
  - !ruby/object:Gem::Version
166
- version: '0'
124
+ version: 1.0.2
167
125
  description: Framework for creating self-describing APIs
168
126
  email: jakub.skokan@vpsfree.cz
169
127
  executables: []
@@ -171,13 +129,17 @@ extensions: []
171
129
  extra_rdoc_files: []
172
130
  files:
173
131
  - .gitignore
132
+ - CHANGELOG
174
133
  - Gemfile
175
134
  - LICENSE.txt
176
135
  - README.md
177
136
  - Rakefile
178
137
  - doc/create-client.md
138
+ - doc/hooks.erb
179
139
  - doc/index.md
140
+ - doc/json-schema.erb
180
141
  - doc/protocol.md
142
+ - doc/protocol.plantuml
181
143
  - haveapi.gemspec
182
144
  - lib/haveapi.rb
183
145
  - lib/haveapi/action.rb
@@ -193,6 +155,7 @@ files:
193
155
  - lib/haveapi/common.rb
194
156
  - lib/haveapi/context.rb
195
157
  - lib/haveapi/example.rb
158
+ - lib/haveapi/exceptions.rb
196
159
  - lib/haveapi/extensions/action_exceptions.rb
197
160
  - lib/haveapi/extensions/base.rb
198
161
  - lib/haveapi/hooks.rb
@@ -208,16 +171,31 @@ files:
208
171
  - lib/haveapi/params/resource.rb
209
172
  - lib/haveapi/public/css/bootstrap-theme.min.css
210
173
  - lib/haveapi/public/css/bootstrap.min.css
174
+ - lib/haveapi/public/doc/protocol.png
211
175
  - lib/haveapi/public/js/bootstrap.min.js
212
176
  - lib/haveapi/public/js/jquery-1.11.1.min.js
213
177
  - lib/haveapi/resource.rb
214
178
  - lib/haveapi/route.rb
215
179
  - lib/haveapi/server.rb
216
180
  - lib/haveapi/spec/helpers.rb
181
+ - lib/haveapi/tasks/hooks.rb
182
+ - lib/haveapi/tasks/yard.rb
217
183
  - lib/haveapi/types.rb
184
+ - lib/haveapi/validator.rb
185
+ - lib/haveapi/validator_chain.rb
186
+ - lib/haveapi/validators/acceptance.rb
187
+ - lib/haveapi/validators/confirmation.rb
188
+ - lib/haveapi/validators/custom.rb
189
+ - lib/haveapi/validators/exclusion.rb
190
+ - lib/haveapi/validators/format.rb
191
+ - lib/haveapi/validators/inclusion.rb
192
+ - lib/haveapi/validators/length.rb
193
+ - lib/haveapi/validators/numericality.rb
194
+ - lib/haveapi/validators/presence.rb
218
195
  - lib/haveapi/version.rb
219
196
  - lib/haveapi/views/doc_layout.erb
220
197
  - lib/haveapi/views/doc_sidebars/create-client.erb
198
+ - lib/haveapi/views/doc_sidebars/json-schema.erb
221
199
  - lib/haveapi/views/doc_sidebars/protocol.erb
222
200
  - lib/haveapi/views/index.erb
223
201
  - lib/haveapi/views/main_layout.erb
@@ -248,3 +226,4 @@ signing_key:
248
226
  specification_version: 4
249
227
  summary: Framework for creating self-describing APIs
250
228
  test_files: []
229
+ has_rdoc: