haveapi 0.13.3 → 0.15.0

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
  SHA256:
3
- metadata.gz: 9428531dfe9ec5702edf5201e2ad8267d03b5c587ee8e2f2d70b86ae003c2b0f
4
- data.tar.gz: 2f754db6d8f10649947fc66df5af1c00d5248644391cfa107382d5eae0e604c4
3
+ metadata.gz: 7d8c351c765bd18dc2ff8a33d5ad0e879e0e837e6c959435f24cd07168ac4d94
4
+ data.tar.gz: 3735e10f7f093a64715220405e4a8a69f769433d0ecd81e55fac048fdeb2e769
5
5
  SHA512:
6
- metadata.gz: 16794d6005d2094375070a1cf491d497174400cc4390d786393b1142ae4229d3ec538816c5962b050ef96baf5fd9b867fe056dea5bf118b2a35051822ae35fe7
7
- data.tar.gz: b5fb4049d0315d5caedb17763706b264f399ada9e3f3e46a74c170e3ee2e8995a02853d8aadfeb7005f65d0ee8e2c38a335ac77251f2eb57c49cdc9177431d58
6
+ metadata.gz: eef44b308fd207bed35e45cba52b2efc63c8f3404804d054fc91f276ddf2d9c648f2cb9f4b8063532e08e9938c28d9592176cec0e16c53c16ef4cbfaffd9e9d9
7
+ data.tar.gz: 5b8a1c07a524dbfd639eae3748cd8fa5603e72c0830f8330fd9682664152509e0fc32455a627f6a86ffa8e2da04d5046ad1220d3dda53836bd39eb3f46ce3c35
data/haveapi.gemspec CHANGED
@@ -17,12 +17,12 @@ Gem::Specification.new do |s|
17
17
  s.add_runtime_dependency 'require_all', '~> 2.0.0'
18
18
  s.add_runtime_dependency 'json'
19
19
  s.add_runtime_dependency 'activesupport', '>= 4.0'
20
- s.add_runtime_dependency 'sinatra', '~> 2.0.5'
21
- s.add_runtime_dependency 'tilt', '~> 2.0.9'
22
- s.add_runtime_dependency 'redcarpet', '~> 3.4'
20
+ s.add_runtime_dependency 'sinatra', '~> 2.1.0'
21
+ s.add_runtime_dependency 'tilt', '~> 2.0.10'
22
+ s.add_runtime_dependency 'redcarpet', '~> 3.5'
23
23
  s.add_runtime_dependency 'rake'
24
24
  s.add_runtime_dependency 'github-markdown'
25
25
  s.add_runtime_dependency 'nesty', '~> 1.0'
26
- s.add_runtime_dependency 'haveapi-client', '~> 0.13.3'
26
+ s.add_runtime_dependency 'haveapi-client', '~> 0.15.0'
27
27
  s.add_runtime_dependency 'mail'
28
28
  end
@@ -72,6 +72,7 @@ module HaveAPI
72
72
  begin
73
73
  subclass.instance_variable_set(:@resource, resource)
74
74
  subclass.instance_variable_set(:@model, resource.model)
75
+ resource.action_defined(subclass)
75
76
  rescue NoMethodError
76
77
  return
77
78
  end
@@ -463,11 +464,11 @@ module HaveAPI
463
464
  end
464
465
 
465
466
  protected
466
- def with_restricted(*args)
467
- if args.empty?
467
+ def with_restricted(**kwargs)
468
+ if kwargs.empty?
468
469
  @authorization.restrictions
469
470
  else
470
- args.first.update(@authorization.restrictions)
471
+ kwargs.update(@authorization.restrictions)
471
472
  end
472
473
  end
473
474
 
@@ -17,8 +17,8 @@ module HaveAPI
17
17
 
18
18
  # Apply restrictions on query which selects objects from database.
19
19
  # Most common usage is restrict user to access only objects he owns.
20
- def restrict(*args)
21
- @restrict << args.first
20
+ def restrict(**kwargs)
21
+ @restrict << kwargs
22
22
  end
23
23
 
24
24
  # Restrict parameters client can set/change.
data/lib/haveapi/hooks.rb CHANGED
@@ -84,7 +84,8 @@ module HaveAPI
84
84
  # +opts+ is a hash and can have following keys:
85
85
  # - desc - why this hook exists, when it's called
86
86
  # - context - the context in which given blocks are called
87
- # - args - hash of block arguments
87
+ # - args - hash of block positional arguments
88
+ # - kwargs - hash of block keyword arguments
88
89
  # - initial - hash of initial values
89
90
  # - ret - hash of return values
90
91
  def self.register_hook(klass, name, opts = {})
@@ -138,6 +139,7 @@ module HaveAPI
138
139
  # @param name [Symbol] hook name
139
140
  # @param where [Class instance] class in whose context hooks are executed
140
141
  # @param args [Array] an array of arguments passed to hooks
142
+ # @param kwargs [Hash] an array of arguments passed to hooks
141
143
  # @param initial [Hash] initial return value
142
144
  # @param instance [Boolean] call instance hooks or not; nil means auto-detect
143
145
  def self.call_for(
@@ -145,6 +147,7 @@ module HaveAPI
145
147
  name,
146
148
  where = nil,
147
149
  args: [],
150
+ kwargs: {},
148
151
  initial: {},
149
152
  instance: nil
150
153
  )
@@ -165,10 +168,10 @@ module HaveAPI
165
168
 
166
169
  hooks.each do |hook|
167
170
  if where
168
- ret = where.instance_exec(initial, *args, &hook)
171
+ ret = where.instance_exec(initial, *args, **kwargs, &hook)
169
172
 
170
173
  else
171
- ret = hook.call(initial, *args)
174
+ ret = hook.call(initial, *args, **kwargs)
172
175
  end
173
176
 
174
177
  initial.update(ret) if ret
@@ -201,48 +204,46 @@ module HaveAPI
201
204
  end
202
205
 
203
206
  # Call all hooks for +name+. see Hooks.call_for.
204
- def call_hooks(*args)
205
- Hooks.call_for(self.to_s, *args)
207
+ def call_hooks(*args, **kwargs)
208
+ Hooks.call_for(self.to_s, *args, **kwargs)
206
209
  end
207
210
  end
208
211
 
209
212
  module InstanceMethods
210
213
  # Call all instance and class hooks.
211
- def call_hooks_for(*args)
212
- ret = call_instance_hooks_for(*args)
214
+ def call_hooks_for(*args, **kwargs)
215
+ ret = call_instance_hooks_for(*args, **kwargs)
213
216
 
214
- if args.last.is_a?(::Hash)
215
- args.last.update(initial: ret)
216
- call_class_hooks_for(*args)
217
- else
218
- call_class_hooks_for(*args, initial: ret)
219
- end
217
+ kwargs[:initial] = ret
218
+ call_class_hooks_for(*args, **kwargs)
220
219
  end
221
220
 
222
221
  # Call only instance hooks.
223
- def call_instance_hooks_for(name, where = nil, args: [], initial: {})
224
- Hooks.call_for(self, name, where, args: args, initial: initial)
222
+ def call_instance_hooks_for(name, where = nil, args: [], kwargs: {}, initial: {})
223
+ Hooks.call_for(self, name, where, args: args, kwargs: kwargs, initial: initial)
225
224
  end
226
225
 
227
226
  # Call only class hooks.
228
- def call_class_hooks_for(name, where = nil, args: [], initial: {})
229
- Hooks.call_for(self.class, name, where, args: args, initial: initial)
227
+ def call_class_hooks_for(name, where = nil, args: [], kwargs: {}, initial: {})
228
+ Hooks.call_for(self.class, name, where, args: args, kwargs: kwargs, initial: initial)
230
229
  end
231
230
 
232
231
  # Call hooks for different +klass+.
233
- def call_hooks_as_for(klass, *args)
234
- ret = call_instance_hooks_as_for(klass, *args)
235
- call_class_hooks_as_for(klass.class, *args, initial: ret)
232
+ def call_hooks_as_for(klass, *args, **kwargs)
233
+ ret = call_instance_hooks_as_for(klass, *args, **kwargs)
234
+
235
+ kwargs[:initial] = ret
236
+ call_class_hooks_as_for(klass.class, *args, **kwargs)
236
237
  end
237
238
 
238
239
  # Call only instance hooks for different +klass+.
239
- def call_instance_hooks_as_for(klass, *args)
240
- Hooks.call_for(klass, *args)
240
+ def call_instance_hooks_as_for(klass, *args, **kwargs)
241
+ Hooks.call_for(klass, *args, **kwargs)
241
242
  end
242
243
 
243
244
  # Call only class hooks for different +klass+.
244
- def call_class_hooks_as_for(klass, *args)
245
- Hooks.call_for(klass, *args)
245
+ def call_class_hooks_as_for(klass, *args, **kwargs)
246
+ Hooks.call_for(klass, *args, **kwargs)
246
247
  end
247
248
 
248
249
  # Connect instance level hook +name+ to +block+.
@@ -78,52 +78,47 @@ module HaveAPI
78
78
  @namespace = n.to_sym if n
79
79
  end
80
80
 
81
- def requires(*args)
82
- add_param(*apply(args, required: true))
81
+ def requires(name, **kwargs)
82
+ add_param(name, apply(kwargs, required: true))
83
83
  end
84
84
 
85
- def optional(*args)
86
- add_param(*apply(args, required: false))
85
+ def optional(name, **kwargs)
86
+ add_param(name, apply(kwargs, required: false))
87
87
  end
88
88
 
89
- def string(*args)
90
- add_param(*apply(args, type: String))
89
+ def string(name, **kwargs)
90
+ add_param(name, apply(kwargs, type: String))
91
91
  end
92
92
 
93
- def text(*args)
94
- add_param(*apply(args, type: Text))
93
+ def text(name, **kwargs)
94
+ add_param(name, apply(kwargs, type: Text))
95
95
  end
96
96
 
97
- def password(*args)
98
- add_param(*apply(args, type: String, protected: true))
97
+ def password(name, **kwargs)
98
+ add_param(name, apply(kwargs, type: String, protected: true))
99
99
  end
100
100
 
101
- def id(*args)
102
- integer(*args)
101
+ def bool(name, **kwargs)
102
+ add_param(name, apply(kwargs, type: Boolean))
103
103
  end
104
104
 
105
- def foreign_key(*args)
106
- integer(*args)
105
+ def integer(name, **kwargs)
106
+ add_param(name, apply(kwargs, type: Integer))
107
107
  end
108
108
 
109
- def bool(*args)
110
- add_param(*apply(args, type: Boolean))
111
- end
112
-
113
- def integer(*args)
114
- add_param(*apply(args, type: Integer))
115
- end
109
+ alias_method :id, :integer
110
+ alias_method :foreign_key, :integer
116
111
 
117
- def float(*args)
118
- add_param(*apply(args, type: Float))
112
+ def float(name, **kwargs)
113
+ add_param(name, apply(kwargs, type: Float))
119
114
  end
120
115
 
121
- def datetime(*args)
122
- add_param(*apply(args, type: Datetime))
116
+ def datetime(name, **kwargs)
117
+ add_param(name, apply(kwargs, type: Datetime))
123
118
  end
124
119
 
125
- def param(*args)
126
- add_param(*args)
120
+ def param(name, **kwargs)
121
+ add_param(name, kwargs)
127
122
  end
128
123
 
129
124
  def use(name, include: nil, exclude: nil)
@@ -153,20 +148,20 @@ module HaveAPI
153
148
  end
154
149
  end
155
150
 
156
- def resource(*args)
157
- add_resource(*args)
151
+ def resource(name, **kwargs)
152
+ add_resource(name, **kwargs)
158
153
  end
159
154
 
160
155
  alias_method :references, :resource
161
156
  alias_method :belongs_to, :resource
162
157
 
163
- def patch(name, changes = {})
158
+ def patch(name, **changes)
164
159
  @params.detect { |p| p.name == name }.patch(changes)
165
160
  end
166
161
 
167
162
  # Action returns custom data.
168
- def custom(*args, &block)
169
- add_param(*apply(args, type: Custom, clean: block))
163
+ def custom(name, **kwargs, &block)
164
+ add_param(name, apply(kwargs, type: Custom, clean: block))
170
165
  end
171
166
 
172
167
  def describe(context)
@@ -274,8 +269,8 @@ module HaveAPI
274
269
  end
275
270
 
276
271
  private
277
- def add_param(*args)
278
- p = Parameters::Typed.new(*args)
272
+ def add_param(name, kwargs)
273
+ p = Parameters::Typed.new(name, kwargs)
279
274
 
280
275
  return if @include && !@include.include?(p.name)
281
276
  return if @exclude && @exclude.include?(p.name)
@@ -283,8 +278,8 @@ module HaveAPI
283
278
  @params << p unless param_exists?(p.name)
284
279
  end
285
280
 
286
- def add_resource(*args)
287
- r = Parameters::Resource.new(*args)
281
+ def add_resource(name, kwargs)
282
+ r = Parameters::Resource.new(name, kwargs)
288
283
 
289
284
  return if @include && !@include.include?(r.name)
290
285
  return if @exclude && @exclude.include?(r.name)
@@ -296,10 +291,9 @@ module HaveAPI
296
291
  !@params.detect { |p| p.name == name }.nil?
297
292
  end
298
293
 
299
- def apply(args, default)
300
- args << {} unless args.last.is_a?(Hash)
301
- args.last.update(default)
302
- args
294
+ def apply(kwargs, **default)
295
+ kwargs.update(default)
296
+ kwargs
303
297
  end
304
298
 
305
299
  def valid_layout?(params)
@@ -14,6 +14,11 @@ module HaveAPI
14
14
  subclass.instance_variable_set(:@obj_type, obj_type)
15
15
  end
16
16
 
17
+ def self.action_defined(klass)
18
+ @actions ||= []
19
+ @actions << klass
20
+ end
21
+
17
22
  def self.params(name, &block)
18
23
  if block
19
24
  @params ||= {}
@@ -23,14 +28,8 @@ module HaveAPI
23
28
  end
24
29
  end
25
30
 
26
- def self.actions
27
- constants.select do |c|
28
- obj = const_get(c)
29
-
30
- if obj.respond_to?(:obj_type) && obj.obj_type == :action
31
- yield obj
32
- end
33
- end
31
+ def self.actions(&block)
32
+ (@actions || []).each(&block)
34
33
  end
35
34
 
36
35
  def self.resources
@@ -40,7 +40,7 @@ module HaveAPI
40
40
  return @current_user if @current_user
41
41
 
42
42
  @current_user = settings.api_server.send(:do_authenticate, v, request)
43
- settings.api_server.call_hooks_for(:post_authenticated, args: @current_user)
43
+ settings.api_server.call_hooks_for(:post_authenticated, args: [@current_user])
44
44
  @current_user
45
45
  end
46
46
 
@@ -121,6 +121,29 @@ module HaveAPI
121
121
  end
122
122
  end
123
123
 
124
+ module DocHelpers
125
+ def format_param_type(param)
126
+ return param[:type] if param[:type] != 'Resource'
127
+ "<a href=\"#root-#{param[:resource].join('-')}-show\">#{param[:type]}</a>"
128
+ end
129
+
130
+ def format_validators(validators)
131
+ ret = ''
132
+ return ret if validators.nil?
133
+
134
+ validators.each do |name, opts|
135
+ ret += "<h5>#{name.to_s.capitalize}</h5>"
136
+ ret += '<dl>'
137
+ opts.each do |k, v|
138
+ ret += "<dt>#{k}</dt><dd>#{v}</dd>"
139
+ end
140
+ ret += '</dl>'
141
+ end
142
+
143
+ ret
144
+ end
145
+ end
146
+
124
147
  def initialize(module_name = HaveAPI.module_name)
125
148
  @module_name = module_name
126
149
  @allowed_headers = ['Content-Type']
@@ -176,6 +199,7 @@ module HaveAPI
176
199
  end
177
200
 
178
201
  helpers ServerHelpers
202
+ helpers DocHelpers
179
203
 
180
204
  before do
181
205
  @formatter = OutputFormatter.new
@@ -1,4 +1,4 @@
1
1
  module HaveAPI
2
2
  PROTOCOL_VERSION = '2.0'
3
- VERSION = '0.13.3'
3
+ VERSION = '0.15.0'
4
4
  end
@@ -0,0 +1,48 @@
1
+ <h2 id="auth-<%= name %>"><%= name.to_s.humanize %></h2>
2
+ <hr>
3
+
4
+ <p><%= info[:description] %></p>
5
+
6
+ <% if name == :token %>
7
+ <dl>
8
+ <dt>HTTP header:</dt>
9
+ <dd><%= info[:http_header] %></dd>
10
+ <dt>Query parameter:</dt>
11
+ <dd><%= info[:query_parameter] %></dd>
12
+ </dl>
13
+ <% end %>
14
+
15
+ <% if info[:resources] %>
16
+ <h2>Resources</h2>
17
+ <% sort_hash(info[:resources]).each do |resource, desc| %>
18
+ <%= erb :"version_page/resource_body", locals: {resource: resource.to_s, info: desc, path: [], prefix: 'root', name: nil} %>
19
+ <% end %>
20
+ <% end %>
21
+
22
+ <% baseid = "auth-#{name}" %>
23
+ <div id="<%= baseid %>-tabbar"></div>
24
+
25
+ <div id="<%= baseid %>-examples">
26
+ <% HaveAPI::ClientExample.clients.each_with_index do |client, i| %>
27
+ <div id="<%= "#{baseid}-#{i}" %>">
28
+ <%= erb :"version_page/client_auth", locals: {client: client, method: name, desc: info} %>
29
+ </div>
30
+ <% end %>
31
+ </div>
32
+
33
+ <script type="text/javascript">
34
+ nojsTabs({
35
+ tabs: document.getElementById('<%= "#{baseid}-examples" %>'),
36
+ titleSelector: 'h4',
37
+ tabBar: document.getElementById('<%= "#{baseid}-tabbar" %>'),
38
+ hiddenClass: 'tab-hidden',
39
+ activeClass: 'active',
40
+ createElement: function (el) {
41
+ if (el.tagName == 'UL')
42
+ el.classList.add('nav', 'nav-tabs');
43
+
44
+ else if (el.tagName == 'LI')
45
+ el.setAttribute('role', 'presentation');
46
+ }
47
+ });
48
+ </script>
@@ -0,0 +1,2 @@
1
+ <h4><%= client.label %></h4>
2
+ <pre><code class="<%= client.code %>"><%= client.auth(host, base_url, api_version, method, desc) %></code></pre>
@@ -0,0 +1,11 @@
1
+ <h6><%= client.label %></h6>
2
+ <% sample = client.new(host, base_url, api_version, r_name, resource, a_name, action) %>
3
+ <% if sample.respond_to?(:example) %>
4
+ <pre><code class="<%= client.code %>"><%= sample.example(example) %></code></pre>
5
+
6
+ <% else %>
7
+ <h6>Request</h6>
8
+ <pre><code class="<%= client.code %>"><%= sample.request(example) %></code></pre>
9
+ <h6>Response</h6>
10
+ <pre><code class="<%= client.code %>"><%= sample.response(example) %></code></pre>
11
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <h4><%= client.label %></h4>
2
+ <pre><code class="<%= client.code %>"><%= client.init(host, base_url, api_version) %></code></pre>
@@ -0,0 +1,163 @@
1
+ <% name ||= resource.humanize %>
2
+ <% resource_path = path.clone << resource %>
3
+ <% resource_info = info %>
4
+ <h2 class="resource" id="<%= "#{prefix}-#{resource}" %>"><%= resource.humanize %></h2>
5
+ <hr>
6
+ <div class="resource-body">
7
+ <p><%= info[:description] %></p>
8
+
9
+ <div class="actions">
10
+ <% sort_hash(info[:actions]).each do |action, info| %>
11
+ <h3 id="<%= "#{prefix}-#{resource}-#{action}" %>"><%= name %> # <%= action.capitalize %></h3>
12
+ <div class="action">
13
+ <dl>
14
+ <dt>Path:</dt>
15
+ <dd><%= info[:method] %> <%= info[:path] %></dd>
16
+ <dt>Description:</dt>
17
+ <dd><%= info[:description] %></dd>
18
+ <dt>Authentication required:</dt>
19
+ <dd><%= info[:auth] ? 'yes' : 'no' %></dd>
20
+ <dt>Aliases:</dt>
21
+ <dd><%= info[:aliases].join(', ') %></dd>
22
+ <dt>Blocking:</dt>
23
+ <dd><%= info[:blocking] ? 'yes' : 'no' %></dd>
24
+ </dl>
25
+
26
+ <h4>Input parameters</h4>
27
+ <div class="parameters">
28
+ <% if info[:input][:parameters].empty? %>
29
+ <p>No parameters.</p>
30
+ <% else %>
31
+ <dl>
32
+ <dt>Layout:</dt>
33
+ <dd><%= info[:input][:layout] %></dd>
34
+ <dt>Namespace:</dt>
35
+ <dd><%= info[:input][:namespace] %></dd>
36
+ </dl>
37
+
38
+ <table class="table table-striped table-hover table-bordered">
39
+ <tr>
40
+ <th>Label</th>
41
+ <th>Name</th>
42
+ <th>Required</th>
43
+ <th>Type</th>
44
+ <th>Validators</th>
45
+ <th>Default</th>
46
+ <th>Description</th>
47
+ </tr>
48
+ <% info[:input][:parameters].each do |param, info| %>
49
+ <tr>
50
+ <td><%= info[:label] %></td>
51
+ <td><%= param %></td>
52
+ <td><%= info[:required] ? 'yes' : 'no' %></td>
53
+ <td><%= format_param_type(info) %></td>
54
+ <td><%= format_validators(info[:validators]) %></td>
55
+ <td><%= info[:default] == :_nil ? '' : info[:default] %></td>
56
+ <td><%= info[:description] %></td>
57
+ </tr>
58
+ <% end %>
59
+ </table>
60
+ <% end %>
61
+ </div>
62
+
63
+ <h4>Output parameters</h4>
64
+ <div class="parameters">
65
+ <% if info[:output][:parameters].empty? && info[:output][:format].nil? %>
66
+ <p>No parameters.</p>
67
+ <% else %>
68
+ <dl>
69
+ <dt>Layout:</dt>
70
+ <dd><%= info[:output][:layout] %></dd>
71
+ <dt>Namespace:</dt>
72
+ <dd><%= info[:output][:namespace] %></dd>
73
+ </dl>
74
+
75
+ <table class="table table-striped table-hover table-bordered">
76
+ <tr>
77
+ <th>Label</th>
78
+ <th>Name</th>
79
+ <th>Type</th>
80
+ <th>Description</th>
81
+ </tr>
82
+ <% info[:output][:parameters].each do |param, info| %>
83
+ <tr>
84
+ <td><%= info[:label] %></td>
85
+ <td><%= param %></td>
86
+ <td><%= format_param_type(info) %></td>
87
+ <td><%= info[:description] %></td>
88
+ </tr>
89
+ <% end %>
90
+ </table>
91
+ <% end %>
92
+ </div>
93
+
94
+ <div class="action-self-description">
95
+ <h4>Self-description</h4>
96
+ <pre><code><%= JSON.pretty_generate(info) %></code></pre>
97
+ </div>
98
+
99
+ <% unless info[:examples].empty? %>
100
+ <h4>Examples</h4>
101
+ <% info[:examples].each_with_index do |example, i| %>
102
+ <h5><%= example[:title].empty? ? "Example ##{i}" : example[:title] %></h5>
103
+ <p><%= example[:comment] %></p>
104
+
105
+ <% baseid = "example-#{resource_path.join('.')}-#{action}-#{i}" %>
106
+ <%# placeholder for tabs %>
107
+ <div id="<%= "#{baseid}-tabbar" %>"></div>
108
+
109
+ <div id="<%= "#{baseid}-examples" %>">
110
+ <% HaveAPI::ClientExample.clients.each_with_index do |client, j| %>
111
+ <div id="<%= "#{baseid}-#{j}" %>">
112
+ <%=
113
+ erb :"version_page/client_example", locals: {
114
+ client: client,
115
+ r_name: resource_path,
116
+ resource: resource_info,
117
+ a_name: action,
118
+ action: info,
119
+ example: example,
120
+ }
121
+ %>
122
+ </div>
123
+ <% end %>
124
+ </div>
125
+
126
+ <script type="text/javascript">
127
+ nojsTabs({
128
+ tabs: document.getElementById('<%= "#{baseid}-examples" %>'),
129
+ titleSelector: 'h6',
130
+ tabBar: document.getElementById('<%= "#{baseid}-tabbar" %>'),
131
+ hiddenClass: 'tab-hidden',
132
+ activeClass: 'active',
133
+ createElement: function (el) {
134
+ if (el.tagName == 'UL')
135
+ el.classList.add('nav', 'nav-tabs');
136
+
137
+ else if (el.tagName == 'LI')
138
+ el.setAttribute('role', 'presentation');
139
+ }
140
+ });
141
+ </script>
142
+ <% end %>
143
+ <% end %>
144
+
145
+ </div>
146
+ <% end %>
147
+ </div>
148
+
149
+ <% unless info[:resources].empty? %>
150
+ <% sort_hash(info[:resources]).each do |r, i| %>
151
+ <%=
152
+ erb :"version_page/resource_body", locals: {
153
+ resource: r,
154
+ info: i,
155
+ path: resource_path,
156
+ prefix: "#{prefix}-#{resource}",
157
+ name: "#{name}.#{r.humanize}",
158
+ }
159
+ %>
160
+ <% end %>
161
+ <% end %>
162
+
163
+ </div> <!-- resource -->
@@ -1,260 +1,3 @@
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
-
24
- <% def render_auth_body(name, info) %>
25
- <h2 id="auth-<%= name %>"><%= name.to_s.humanize %></h2>
26
- <hr>
27
-
28
- <p><%= info[:description] %></p>
29
-
30
- <% if name == :token %>
31
- <dl>
32
- <dt>HTTP header:</dt>
33
- <dd><%= info[:http_header] %></dd>
34
- <dt>Query parameter:</dt>
35
- <dd><%= info[:query_parameter] %></dd>
36
- </dl>
37
- <% end %>
38
-
39
- <% if info[:resources] %>
40
- <h2>Resources</h2>
41
- <% sort_hash(info[:resources]).each do |resource, desc| %>
42
- <% render_resource_body(resource.to_s, desc, 'auth') %>
43
- <% end %>
44
- <% end %>
45
-
46
- <% baseid = "auth-#{name}" %>
47
- <div id="<%= baseid %>-tabbar"></div>
48
-
49
- <div id="<%= baseid %>-examples">
50
- <% HaveAPI::ClientExample.clients.each_with_index do |client, i| %>
51
- <div id="<%= "#{baseid}-#{i}" %>">
52
- <% render_client_auth(client, name, info) %>
53
- </div>
54
- <% end %>
55
- </div>
56
-
57
- <script type="text/javascript">
58
- nojsTabs({
59
- tabs: document.getElementById('<%= "#{baseid}-examples" %>'),
60
- titleSelector: 'h4',
61
- tabBar: document.getElementById('<%= "#{baseid}-tabbar" %>'),
62
- hiddenClass: 'tab-hidden',
63
- activeClass: 'active',
64
- createElement: function (el) {
65
- if (el.tagName == 'UL')
66
- el.classList.add('nav', 'nav-tabs');
67
-
68
- else if (el.tagName == 'LI')
69
- el.setAttribute('role', 'presentation');
70
- }
71
- });
72
- </script>
73
- <% end %>
74
-
75
- <% def render_resource_body(resource, info, path = [], prefix='root', name=nil) %>
76
- <% name ||= resource.humanize %>
77
- <% resource_path = path.clone << resource %>
78
- <% resource_info = info %>
79
- <h2 class="resource" id="<%= "#{prefix}-#{resource}" %>"><%= resource.humanize %></h2>
80
- <hr>
81
- <div class="resource-body">
82
- <p><%= info[:description] %></p>
83
-
84
- <div class="actions">
85
- <% sort_hash(info[:actions]).each do |action, info| %>
86
- <h3 id="<%= "#{prefix}-#{resource}-#{action}" %>"><%= name %> # <%= action.capitalize %></h3>
87
- <div class="action">
88
- <dl>
89
- <dt>Path:</dt>
90
- <dd><%= info[:method] %> <%= info[:path] %></dd>
91
- <dt>Description:</dt>
92
- <dd><%= info[:description] %></dd>
93
- <dt>Authentication required:</dt>
94
- <dd><%= info[:auth] ? 'yes' : 'no' %></dd>
95
- <dt>Aliases:</dt>
96
- <dd><%= info[:aliases].join(', ') %></dd>
97
- <dt>Blocking:</dt>
98
- <dd><%= info[:blocking] ? 'yes' : 'no' %></dd>
99
- </dl>
100
-
101
- <h4>Input parameters</h4>
102
- <div class="parameters">
103
- <% if info[:input][:parameters].empty? %>
104
- <p>No parameters.</p>
105
- <% else %>
106
- <dl>
107
- <dt>Layout:</dt>
108
- <dd><%= info[:input][:layout] %></dd>
109
- <dt>Namespace:</dt>
110
- <dd><%= info[:input][:namespace] %></dd>
111
- </dl>
112
-
113
- <table class="table table-striped table-hover table-bordered">
114
- <tr>
115
- <th>Label</th>
116
- <th>Name</th>
117
- <th>Required</th>
118
- <th>Type</th>
119
- <th>Validators</th>
120
- <th>Default</th>
121
- <th>Description</th>
122
- </tr>
123
- <% info[:input][:parameters].each do |param, info| %>
124
- <tr>
125
- <td><%= info[:label] %></td>
126
- <td><%= param %></td>
127
- <td><%= info[:required] ? 'yes' : 'no' %></td>
128
- <td><%= format_param_type(info) %></td>
129
- <td><%= format_validators(info[:validators]) %></td>
130
- <td><%= info[:default] == :_nil ? '' : info[:default] %></td>
131
- <td><%= info[:description] %></td>
132
- </tr>
133
- <% end %>
134
- </table>
135
- <% end %>
136
- </div>
137
-
138
- <h4>Output parameters</h4>
139
- <div class="parameters">
140
- <% if info[:output][:parameters].empty? && info[:output][:format].nil? %>
141
- <p>No parameters.</p>
142
- <% else %>
143
- <dl>
144
- <dt>Layout:</dt>
145
- <dd><%= info[:output][:layout] %></dd>
146
- <dt>Namespace:</dt>
147
- <dd><%= info[:output][:namespace] %></dd>
148
- </dl>
149
-
150
- <table class="table table-striped table-hover table-bordered">
151
- <tr>
152
- <th>Label</th>
153
- <th>Name</th>
154
- <th>Type</th>
155
- <th>Description</th>
156
- </tr>
157
- <% info[:output][:parameters].each do |param, info| %>
158
- <tr>
159
- <td><%= info[:label] %></td>
160
- <td><%= param %></td>
161
- <td><%= format_param_type(info) %></td>
162
- <td><%= info[:description] %></td>
163
- </tr>
164
- <% end %>
165
- </table>
166
- <% end %>
167
- </div>
168
-
169
- <div class="action-self-description">
170
- <h4>Self-description</h4>
171
- <pre><code><%= JSON.pretty_generate(info) %></code></pre>
172
- </div>
173
-
174
- <% unless info[:examples].empty? %>
175
- <h4>Examples</h4>
176
- <% info[:examples].each_with_index do |example, i| %>
177
- <h5><%= example[:title].empty? ? "Example ##{i}" : example[:title] %></h5>
178
- <p><%= example[:comment] %></p>
179
-
180
- <% baseid = "example-#{resource_path.join('.')}-#{action}-#{i}" %>
181
- <%# placeholder for tabs %>
182
- <div id="<%= "#{baseid}-tabbar" %>"></div>
183
-
184
- <div id="<%= "#{baseid}-examples" %>">
185
- <% HaveAPI::ClientExample.clients.each_with_index do |client, j| %>
186
- <div id="<%= "#{baseid}-#{j}" %>">
187
- <%
188
- render_client_example(
189
- client,
190
- resource_path,
191
- resource_info,
192
- action,
193
- info,
194
- example
195
- )
196
- %>
197
- </div>
198
- <% end %>
199
- </div>
200
-
201
- <script type="text/javascript">
202
- nojsTabs({
203
- tabs: document.getElementById('<%= "#{baseid}-examples" %>'),
204
- titleSelector: 'h6',
205
- tabBar: document.getElementById('<%= "#{baseid}-tabbar" %>'),
206
- hiddenClass: 'tab-hidden',
207
- activeClass: 'active',
208
- createElement: function (el) {
209
- if (el.tagName == 'UL')
210
- el.classList.add('nav', 'nav-tabs');
211
-
212
- else if (el.tagName == 'LI')
213
- el.setAttribute('role', 'presentation');
214
- }
215
- });
216
- </script>
217
- <% end %>
218
- <% end %>
219
-
220
- </div>
221
- <% end %>
222
- </div>
223
-
224
- <% unless info[:resources].empty? %>
225
- <% sort_hash(info[:resources]).each do |r, i| %>
226
- <% render_resource_body(r, i, resource_path, "#{prefix}-#{resource}", "#{name}.#{r.humanize}") %>
227
- <% end %>
228
- <% end %>
229
-
230
- </div> <!-- resource -->
231
- <% end %>
232
-
233
- <% def render_client_init(client) %>
234
- <h4><%= client.label %></h4>
235
- <pre><code class="<%= client.code %>"><%= client.init(host, base_url, api_version) %></code></pre>
236
- <% end %>
237
-
238
- <% def render_client_auth(client, method, desc) %>
239
- <h4><%= client.label %></h4>
240
- <pre><code class="<%= client.code %>"><%= client.auth(host, base_url, api_version, method, desc) %></code></pre>
241
- <% end %>
242
-
243
- <% def render_client_example(client, r_name, resource, a_name, action, example) %>
244
- <h6><%= client.label %></h6>
245
- <% sample = client.new(host, base_url, api_version, r_name, resource, a_name, action) %>
246
- <% if sample.respond_to?(:example) %>
247
- <pre><code class="<%= client.code %>"><%= sample.example(example) %></code></pre>
248
-
249
- <% else %>
250
- <h6>Request</h6>
251
- <pre><code class="<%= client.code %>"><%= sample.request(example) %></code></pre>
252
- <h6>Response</h6>
253
- <pre><code class="<%= client.code %>"><%= sample.response(example) %></code></pre>
254
- <% end %>
255
- <% end %>
256
-
257
-
258
1
  <h1 id="api">API v<%= @v %></h1>
259
2
 
260
3
  <ol class="breadcrumb">
@@ -295,7 +38,7 @@ end
295
38
  <div id="init-examples">
296
39
  <% HaveAPI::ClientExample.clients.each_with_index do |client, i| %>
297
40
  <div id="<%= "init-#{i}" %>">
298
- <% render_client_init(client) %>
41
+ <%= erb :"version_page/client_init", locals: {client: client} %>
299
42
  </div>
300
43
  <% end %>
301
44
  </div>
@@ -319,14 +62,22 @@ nojsTabs({
319
62
 
320
63
  <h1 id="auth">Authentication methods</h1>
321
64
  <% @help[:authentication].each do |name, info| %>
322
- <% render_auth_body(name, info) %>
65
+ <%= erb :"version_page/auth_body", locals: {name: name, info: info} %>
323
66
  <% end %>
324
67
 
325
68
  <h1 id="resources">Resources</h1>
326
69
  <p>Follows a list of all resources in this API and their actions.</p>
327
70
 
328
71
  <% sort_hash(@help[:resources]).each do |resource, info| %>
329
- <% render_resource_body(resource, info) %>
72
+ <%=
73
+ erb :"version_page/resource_body", locals: {
74
+ resource: resource,
75
+ info: info,
76
+ path: [],
77
+ prefix: 'root',
78
+ name: nil,
79
+ }
80
+ %>
330
81
  <% end %>
331
82
  </div>
332
83
 
@@ -0,0 +1,20 @@
1
+ <ul>
2
+ <% methods.each do |method, info| %>
3
+ <li>
4
+ <a href="#auth-<%= method %>"><%= method.to_s.humanize %></a>
5
+ <% if info[:resources] %>
6
+ <ul>
7
+ <% sort_hash(info[:resources]).each do |resource, info| %>
8
+ <%=
9
+ erb :"version_sidebar/resource_nav", locals: {
10
+ resource: resource.to_s,
11
+ info: info,
12
+ prefix: "auth-#{method}",
13
+ }
14
+ %>
15
+ <% end %>
16
+ </ul>
17
+ <% end %>
18
+ </li>
19
+ <% end %>
20
+ </ul>
@@ -0,0 +1,21 @@
1
+ <li>
2
+ <a href="#<%= "#{prefix}-#{resource}" %>">.<%= resource.humanize %></a>
3
+
4
+ <ul>
5
+ <% sort_hash(info[:actions]).each do |action, info| %>
6
+ <li>
7
+ <a href="#<%= "#{prefix}-#{resource}-#{action}" %>">#<%= action.capitalize %></a>
8
+ </li>
9
+ <% end %>
10
+
11
+ <% sort_hash(info[:resources]).each do |r, i| %>
12
+ <%=
13
+ erb :"version_sidebar/resource_nav", locals: {
14
+ resource: r,
15
+ info: i,
16
+ prefix: "#{prefix}-#{resource}",
17
+ }
18
+ %>
19
+ <% end %>
20
+ </ul>
21
+ </li>
@@ -1,38 +1,3 @@
1
- <% def render_auth_nav(methods) %>
2
- <ul>
3
- <% methods.each do |method, info| %>
4
- <li>
5
- <a href="#auth-<%= method %>"><%= method.to_s.humanize %></a>
6
- <% if info[:resources] %>
7
- <ul>
8
- <% sort_hash(info[:resources]).each do |resource, info| %>
9
- <% render_resource_nav(resource.to_s, info, "auth-#{method}") %>
10
- <% end %>
11
- </ul>
12
- <% end %>
13
- </li>
14
- <% end %>
15
- </ul>
16
- <% end %>
17
-
18
- <% def render_resource_nav(resource, info, prefix='root') %>
19
- <li>
20
- <a href="#<%= "#{prefix}-#{resource}" %>">.<%= resource.humanize %></a>
21
-
22
- <ul>
23
- <% sort_hash(info[:actions]).each do |action, info| %>
24
- <li>
25
- <a href="#<%= "#{prefix}-#{resource}-#{action}" %>">#<%= action.capitalize %></a>
26
- </li>
27
- <% end %>
28
-
29
- <% sort_hash(info[:resources]).each do |r, i| %>
30
- <% render_resource_nav(r, i, "#{prefix}-#{resource}") %>
31
- <% end %>
32
- </ul>
33
- </li>
34
- <% end %>
35
-
36
1
  <h1>Authentication</h1>
37
2
  <p class="authentication">
38
3
  <% if current_user %>
@@ -54,11 +19,17 @@
54
19
  <li><a href="#api">API v<%= @v %></a></li>
55
20
  <li>
56
21
  <a href="#auth">Authentication</a>
57
- <% render_auth_nav(@help[:authentication]) %>
22
+ <%= erb :"version_sidebar/auth_nav", locals: {methods: @help[:authentication]} %>
58
23
  </li>
59
24
  <li><a href="#resources">Resources</a></li>
60
- <% sort_hash(@help[:resources]).each do |resource, info| %>
61
- <% render_resource_nav(resource, info) %>
25
+ <% sort_hash(@help[:resources]).each do |resource, info| %>
26
+ <%=
27
+ erb :"version_sidebar/resource_nav", locals: {
28
+ resource: resource,
29
+ info: info,
30
+ prefix: 'root',
31
+ }
32
+ %>
62
33
  <% end %>
63
34
  </ul>
64
35
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.3
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1970-01-01 00:00:00.000000000 Z
11
+ date: 1980-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: require_all
@@ -58,42 +58,42 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.0.5
61
+ version: 2.1.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.0.5
68
+ version: 2.1.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: tilt
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 2.0.9
75
+ version: 2.0.10
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 2.0.9
82
+ version: 2.0.10
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: redcarpet
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.4'
89
+ version: '3.5'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.4'
96
+ version: '3.5'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.13.3
145
+ version: 0.15.0
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 0.13.3
152
+ version: 0.15.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: mail
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -268,7 +268,14 @@ files:
268
268
  - lib/haveapi/views/index.erb
269
269
  - lib/haveapi/views/main_layout.erb
270
270
  - lib/haveapi/views/version_page.erb
271
+ - lib/haveapi/views/version_page/auth_body.erb
272
+ - lib/haveapi/views/version_page/client_auth.erb
273
+ - lib/haveapi/views/version_page/client_example.erb
274
+ - lib/haveapi/views/version_page/client_init.erb
275
+ - lib/haveapi/views/version_page/resource_body.erb
271
276
  - lib/haveapi/views/version_sidebar.erb
277
+ - lib/haveapi/views/version_sidebar/auth_nav.erb
278
+ - lib/haveapi/views/version_sidebar/resource_nav.erb
272
279
  - shell.nix
273
280
  - spec/action/dsl_spec.rb
274
281
  - spec/authorization_spec.rb
@@ -289,11 +296,11 @@ files:
289
296
  - spec/validators/length_spec.rb
290
297
  - spec/validators/numericality_spec.rb
291
298
  - spec/validators/presence_spec.rb
292
- homepage:
299
+ homepage:
293
300
  licenses:
294
301
  - MIT
295
302
  metadata: {}
296
- post_install_message:
303
+ post_install_message:
297
304
  rdoc_options: []
298
305
  require_paths:
299
306
  - lib
@@ -308,8 +315,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
308
315
  - !ruby/object:Gem::Version
309
316
  version: '0'
310
317
  requirements: []
311
- rubygems_version: 3.0.6
312
- signing_key:
318
+ rubygems_version: 3.2.26
319
+ signing_key:
313
320
  specification_version: 4
314
321
  summary: Framework for creating self-describing APIs
315
322
  test_files: []