jsonapionify 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NGNlYzQxYWRmZDlmZWJhODFiNDEwY2E3ZmZkNmRlNzA0YzhjODU1Zg==
4
+ MGU3ZWE5YTE4YTNiNjE1NTdiYzI2NTM2Y2UyYTA1ZTllNjVhZGQ3Ng==
5
5
  data.tar.gz: !binary |-
6
- ZGY4YjVhMWZiZGY0NmM5YWNiZGRjOGUxY2ViMmRlZTNkNTA3YjhhNw==
6
+ OWViOTNhOGFmYmE2YmNhNGZhNDMzM2FhMzUzMmZmYTY2ZjY0NTNjZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODE5ZWI5MjkxNjhhYzRjYzcwNWJlN2U1MTRlZjM4MjFiMDVlN2FhMzA3NDhh
10
- YTc4Zjg1MzY0ZjQ3Zjg2YmUyZDdmZjQyM2ZlYzY4YmRjZjA4OTBmZjA5NDZm
11
- YTRiZTAwOTgzNGFkYjY0YWYyZGMwNmEwZmE4YjM4OGY3NzgyY2Y=
9
+ MjhkNTFiZmZjNzc2ZjRmOTc2ZWQ2M2Y5ZGRkOWIyZTQzOTAxNTA5MDk0Yzg0
10
+ YjgxYjJhYWNmOTg5M2E5MDZhZjc4ZTE4ODI5YTVjZjM0YTg1YzEzMjYyYjBh
11
+ NmY2ZGRlMzAzY2Q5NTJkZGMwNGM1NjA2NzNhNmYxM2RmNGM1NGE=
12
12
  data.tar.gz: !binary |-
13
- YjIxZmE5M2Y4YTVkYWIzOTg1MmVlNjhhMmU5ODU5MzY4YTQ1ZmZkMDM3OTVl
14
- MGZmZGJhM2ViYTEyYjZkZTg0YjY4OTA5ZmIyZGE2OGUyNTg5ODk3Mjk0OTJm
15
- OWU3YmNmMTllMmFkYThmYmRjNDUyNGRjZTNlMDVhMzM0YWJiNjg=
13
+ OWI4OWNkMWIyNTI3MDgzZGYyYzkxODZmMDNmNDI3MDYyYmZjYjZlZjI3YTFj
14
+ NjRlNzQ0ODJkNGU4OTU1NGNhZTc4YmVhOTdlZTZjNDY0ZGVlMjZjODI3MDUw
15
+ YzhkOTExMjViZTBiNjRlMmVkZTVjMjZlNWJmOGVkZTZhMjBhYjE=
@@ -0,0 +1,78 @@
1
+ module JSONAPIonify::Api
2
+ module Action::Documentation
3
+ def documentation_object(base, resource, name, include_path, label)
4
+ url = build_path(base, name.to_s, include_path)
5
+ path = URI.parse(url).path
6
+ OpenStruct.new(
7
+ id: [request_method, path].join('-').parameterize,
8
+ label: label,
9
+ sample_requests: example_requests(resource, url)
10
+ )
11
+ end
12
+
13
+ def example_input(resource)
14
+ request = Server::Request.env_for('http://example.org', request_method)
15
+ context = resource.new(
16
+ request: request,
17
+ context_definitions: sample_context(resource)
18
+ ).exec { |c| c }
19
+ case @example_input
20
+ when :resource
21
+ {
22
+ 'data' => resource.build_resource(
23
+ context,
24
+ resource.example_instance_for_action(name, context),
25
+ relationships: false,
26
+ links: false,
27
+ fields: resource.fields_for_action(name, context)
28
+ ).as_json
29
+ }.to_json
30
+ when :resource_identifier
31
+ {
32
+ 'data' => resource.build_resource_identifier(
33
+ resource.example_instance_for_action(name, context)
34
+ ).as_json
35
+ }.to_json
36
+ when Proc
37
+ @example_input.call
38
+ end
39
+ end
40
+
41
+ def example_requests(resource, url)
42
+ responses.map do |response|
43
+ opts = {}
44
+ opts['CONTENT_TYPE'] = content_type if @example_input
45
+ accept = response.accept || response.example_accept
46
+ opts['HTTP_ACCEPT'] = accept
47
+ if content_type == 'application/vnd.api+json' && @example_input
48
+ opts[:input] = example_input(resource)
49
+ end
50
+ url = "#{url}.#{response.extension}" if response.extension
51
+ request = Server::Request.env_for(url, request_method, opts)
52
+ response = Server::MockResponse.new(*sample_request(resource, request))
53
+
54
+ OpenStruct.new(
55
+ request: request.http_string,
56
+ response: response.http_string
57
+ )
58
+ end
59
+ end
60
+
61
+ def sample_context(resource)
62
+ resource.context_definitions.dup.tap do |defs|
63
+ collection_context = proc do |context|
64
+ 3.times.map { resource.example_instance_for_action(action.name, context) }
65
+ end
66
+ defs[:_is_example_] = Context.new(readonly: true) { true }
67
+ defs[:collection] = Context.new(&collection_context)
68
+ defs[:paginated_collection] = Context.new { |context| context.collection }
69
+ defs[:instance] = Context.new(readonly: true) { |context| context.collection.first }
70
+ defs[:owner_context] = Context.new(readonly: true) { ContextDelegate::Mock.new } if defs.has_key? :owner_context
71
+ end
72
+ end
73
+
74
+ def sample_request(resource, request)
75
+ call(resource, request, context_definitions: sample_context(resource), callbacks: false)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,13 @@
1
+ module JSONAPIonify::Api
2
+ module Action::Dummy
3
+ def dummy(&block)
4
+ new(nil, nil, &block)
5
+ end
6
+
7
+ def error(name, &block)
8
+ dummy do
9
+ error_now name, &block
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,20 +2,15 @@ require 'unstrict_proc'
2
2
 
3
3
  module JSONAPIonify::Api
4
4
  class Action
5
+ extend JSONAPIonify::Autoload
6
+ autoload_all
7
+ extend Dummy
8
+ include Documentation
9
+
5
10
  attr_reader :name, :block, :content_type, :responses, :prepend,
6
11
  :path, :request_method, :only_associated, :cacheable,
7
12
  :callbacks
8
13
 
9
- def self.dummy(&block)
10
- new(nil, nil, &block)
11
- end
12
-
13
- def self.error(name, &block)
14
- dummy do
15
- error_now name, &block
16
- end
17
- end
18
-
19
14
  def initialize(name, request_method, path = nil,
20
15
  example_input: nil,
21
16
  content_type: nil,
@@ -38,6 +33,7 @@ module JSONAPIonify::Api
38
33
  end
39
34
 
40
35
  def initialize_copy(new_instance)
36
+ puts "DUPED!"
41
37
  super
42
38
  %i{@responses}.each do |ivar|
43
39
  value = instance_variable_get(ivar)
@@ -78,61 +74,6 @@ module JSONAPIonify::Api
78
74
  request.path_info.match(path_regex(base, name, include_path))
79
75
  end
80
76
 
81
- def documentation_object(base, resource, name, include_path, label)
82
- url = build_path(base, name.to_s, include_path)
83
- path = URI.parse(url).path
84
- OpenStruct.new(
85
- id: [request_method, path].join('-').parameterize,
86
- label: label,
87
- sample_requests: example_requests(resource, url)
88
- )
89
- end
90
-
91
- def example_input(resource)
92
- request = Server::Request.env_for('http://example.org', request_method)
93
- context = ContextDelegate::Mock.new(
94
- request: request, resource: resource.new, _is_example_: true, includes: []
95
- )
96
- case @example_input
97
- when :resource
98
- {
99
- 'data' => resource.build_resource(
100
- context,
101
- resource.example_instance_for_action(name, context),
102
- relationships: false,
103
- links: false,
104
- fields: resource.fields_for_action(name, context)
105
- ).as_json
106
- }.to_json
107
- when :resource_identifier
108
- {
109
- 'data' => resource.build_resource_identifier(
110
- resource.example_instance_for_action(name, context)
111
- ).as_json
112
- }.to_json
113
- when Proc
114
- @example_input.call
115
- end
116
- end
117
-
118
- def example_requests(resource, url)
119
- responses.map do |response|
120
- opts = {}
121
- opts['CONTENT_TYPE'] = content_type if @example_input
122
- opts['HTTP_ACCEPT'] = response.accept
123
- if content_type == 'application/vnd.api+json' && @example_input
124
- opts[:input] = example_input(resource)
125
- end
126
- request = Server::Request.env_for(url, request_method, opts)
127
- response = Server::MockResponse.new(*sample_request(resource, request))
128
-
129
- OpenStruct.new(
130
- request: request.http_string,
131
- response: response.http_string
132
- )
133
- end
134
- end
135
-
136
77
  def supports_content_type?(request)
137
78
  @content_type == request.content_type || !request.has_body?
138
79
  end
@@ -154,23 +95,6 @@ module JSONAPIonify::Api
154
95
  self
155
96
  end
156
97
 
157
- def sample_context(resource)
158
- resource.context_definitions.dup.tap do |defs|
159
- collection_context = proc do |context|
160
- 3.times.map { resource.example_instance_for_action(action.name, context) }
161
- end
162
- defs[:_is_example_] = Context.new(readonly: true) { true }
163
- defs[:collection] = Context.new(&collection_context)
164
- defs[:paginated_collection] = Context.new { |context| context.collection }
165
- defs[:instance] = Context.new(readonly: true) { |context| context.collection.first }
166
- defs[:owner_context] = Context.new(readonly: true) { ContextDelegate::Mock.new } if defs.has_key? :owner_context
167
- end
168
- end
169
-
170
- def sample_request(resource, request)
171
- call(resource, request, context_definitions: sample_context(resource), callbacks: false)
172
- end
173
-
174
98
  def call(resource, request, callbacks: self.callbacks, **opts)
175
99
  resource.new(
176
100
  request: request,
@@ -0,0 +1,25 @@
1
+ module JSONAPIonify::Api
2
+ module Attribute::Documentation
3
+ def options_json_for_action(action_name, context)
4
+ {
5
+ name: @name,
6
+ type: @type.to_s,
7
+ description: JSONAPIonify::Documentation.onelinify_markdown(description),
8
+ example: example(context.resource.class.generate_id)
9
+ }.tap do |opts|
10
+ opts[:not_null] = true if @type.not_null?
11
+ opts[:required] = true if required_for_action?(action_name, context)
12
+ end
13
+ end
14
+
15
+ def documentation_object
16
+ OpenStruct.new(
17
+ name: name,
18
+ type: type.name,
19
+ required: required ? Array.wrap(required).join(', ') : false,
20
+ description: JSONAPIonify::Documentation.render_markdown(description),
21
+ allow: allow
22
+ )
23
+ end
24
+ end
25
+ end
@@ -2,6 +2,10 @@ require 'unstrict_proc'
2
2
 
3
3
  module JSONAPIonify::Api
4
4
  class Attribute
5
+ extend JSONAPIonify::Autoload
6
+ autoload_all
7
+
8
+ include Documentation
5
9
  using UnstrictProc
6
10
  attr_reader :name, :type, :description, :read, :write, :required, :block
7
11
 
@@ -104,18 +108,6 @@ module JSONAPIonify::Api
104
108
  (required === true || Array.wrap(required).include?(action_name))
105
109
  end
106
110
 
107
- def options_json_for_action(action_name, context)
108
- {
109
- name: @name,
110
- type: @type.to_s,
111
- description: JSONAPIonify::Documentation.onelinify_markdown(description),
112
- example: example(context.resource.class.generate_id)
113
- }.tap do |opts|
114
- opts[:not_null] = true if @type.not_null?
115
- opts[:required] = true if required_for_action?(action_name, context)
116
- end
117
- end
118
-
119
111
  def read?
120
112
  !!@read
121
113
  end
@@ -135,16 +127,6 @@ module JSONAPIonify::Api
135
127
  end
136
128
  end
137
129
 
138
- def documentation_object
139
- OpenStruct.new(
140
- name: name,
141
- type: type.name,
142
- required: Array.wrap(required).join(', '),
143
- description: JSONAPIonify::Documentation.render_markdown(description),
144
- allow: allow
145
- )
146
- end
147
-
148
130
  def allow
149
131
  Array.new.tap do |ary|
150
132
  ary << 'read' if read?
@@ -1,5 +1,5 @@
1
1
  module JSONAPIonify::Api
2
- module Base::DocHelper
2
+ module Base::Documentation
3
3
  Link = Struct.new(:title, :href)
4
4
 
5
5
  def self.extended(klass)
@@ -6,7 +6,7 @@ module JSONAPIonify::Api
6
6
  extend JSONAPIonify::Autoload
7
7
  autoload_all
8
8
  extend AppBuilder
9
- extend DocHelper
9
+ extend Documentation
10
10
  extend ClassMethods
11
11
  extend Delegation
12
12
  extend ResourceDefinitions
@@ -0,0 +1,18 @@
1
+ module JSONAPIonify::Api
2
+ module Relationship::Documentation
3
+ def options_json
4
+ {
5
+ name: name,
6
+ type: resource.type,
7
+ relationship_type: self.class.name.split(':').last.downcase
8
+ }
9
+ end
10
+
11
+ def documentation_object
12
+ OpenStruct.new(
13
+ name: name,
14
+ resource: resource_class.type
15
+ )
16
+ end
17
+ end
18
+ end
@@ -4,6 +4,7 @@ module JSONAPIonify::Api
4
4
  autoload_all
5
5
 
6
6
  extend Blocks
7
+ include Documentation
7
8
 
8
9
  prepend_class do
9
10
  remove_action :delete, :update
@@ -73,21 +74,6 @@ module JSONAPIonify::Api
73
74
  @resolve = resolve
74
75
  end
75
76
 
76
- def options_json
77
- {
78
- name: name,
79
- type: resource.type,
80
- relationship_type: self.class.name.split(':').last.downcase
81
- }
82
- end
83
-
84
- def documentation_object
85
- OpenStruct.new(
86
- name: name,
87
- resource: resource_class.type
88
- )
89
- end
90
-
91
77
  def resource_class
92
78
  @resource_class ||= begin
93
79
  rel = self
@@ -50,27 +50,6 @@ module JSONAPIonify::Api
50
50
  end.to_s
51
51
  end
52
52
 
53
- def documented_actions_in_order
54
- indexes = %i{list create read update delete add replace remove}
55
- documented_actions.reject do |a, *|
56
- ['HEAD', 'OPTIONS'].include? a.request_method
57
- end.sort_by do |action, *|
58
- indexes.index(action.name) || indexes.length
59
- end
60
- end
61
-
62
- def documentation_object(base_url)
63
- OpenStruct.new(
64
- name: type,
65
- description: JSONAPIonify::Documentation.render_markdown(@description || ''),
66
- relationships: relationships.map { |r| r.documentation_object },
67
- attributes: attributes.sort_by(&:name).map(&:documentation_object),
68
- actions: documented_actions_in_order.map do |action, base, args|
69
- action.documentation_object File.join(base_url, base), *args
70
- end
71
- )
72
- end
73
-
74
53
  def cache(store, *args)
75
54
  self.cache_store = ActiveSupport::Cache.lookup_store(store, *args)
76
55
  end
@@ -4,7 +4,7 @@ module JSONAPIonify::Api
4
4
  included do
5
5
  id :id
6
6
  scope { self.type.classify.constantize }
7
- collection do |scope|
7
+ collection do |scope, context|
8
8
  if defined?(ActiveRecord) && scope < ActiveRecord::Base && scope.is_a?(Class)
9
9
  scope.all
10
10
  else
@@ -0,0 +1,57 @@
1
+ module JSONAPIonify::Api
2
+ module Resource::Documentation
3
+
4
+ def self.extended(mod)
5
+ mod.example_id_generator { |val| val }
6
+ end
7
+
8
+ def documented_actions_in_order
9
+ indexes = %i{list create read update delete add replace remove}
10
+ documented_actions.reject do |a, *|
11
+ ['HEAD', 'OPTIONS'].include? a.request_method
12
+ end.sort_by do |action, *|
13
+ indexes.index(action.name) || indexes.length
14
+ end
15
+ end
16
+
17
+ def documentation_object(base_url)
18
+ OpenStruct.new(
19
+ name: type,
20
+ description: JSONAPIonify::Documentation.render_markdown(@description || ''),
21
+ relationships: relationships.map { |r| r.documentation_object },
22
+ attributes: attributes.sort_by(&:name).map(&:documentation_object),
23
+ actions: documented_actions_in_order.map do |action, base, args|
24
+ action.documentation_object File.join(base_url, base), *args
25
+ end
26
+ )
27
+ end
28
+
29
+ def example_id_generator(&block)
30
+ index = 0
31
+ define_singleton_method(:generate_id) do
32
+ instance_exec index += 1, &block
33
+ end
34
+ context :example_id do
35
+ self.class.generate_id
36
+ end
37
+ end
38
+
39
+ def example_instance_for_action(action, context)
40
+ id = generate_id
41
+ OpenStruct.new.tap do |instance|
42
+ instance.send "#{id_attribute}=", id.to_s
43
+ actionable_attributes = attributes.select do |attr|
44
+ attr.supports_read_for_action?(action, context)
45
+ end
46
+ actionable_attributes.each do |attribute|
47
+ instance.send "#{attribute.name}=", attribute.example(id)
48
+ end
49
+
50
+ instance.define_singleton_method :method_missing do |*args|
51
+ self
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -9,6 +9,7 @@ module JSONAPIonify::Api
9
9
 
10
10
  extend Definitions
11
11
  extend ClassMethods
12
+ extend Documentation
12
13
 
13
14
  include ErrorHandling
14
15
  include Includer
@@ -32,31 +33,6 @@ module JSONAPIonify::Api
32
33
  )
33
34
  end
34
35
 
35
- def self.example_id_generator(&block)
36
- index = 0
37
- define_singleton_method(:generate_id) do
38
- instance_exec index += 1, &block
39
- end
40
- context :example_id do
41
- self.class.generate_id
42
- end
43
- end
44
-
45
- def self.example_instance_for_action(action, context)
46
- id = generate_id
47
- OpenStruct.new.tap do |instance|
48
- instance.send "#{id_attribute}=", id.to_s
49
- actionable_attributes = attributes.select do |attr|
50
- attr.supports_read_for_action?(action, context)
51
- end
52
- actionable_attributes.each do |attribute|
53
- instance.send "#{attribute.name}=", attribute.example(id)
54
- end
55
- end
56
- end
57
-
58
- example_id_generator { |val| val }
59
-
60
36
  attr_reader :errors, :action, :response_headers
61
37
 
62
38
  def initialize(
@@ -1,12 +1,15 @@
1
1
  module JSONAPIonify::Api
2
2
  class Response
3
3
  attr_reader :action, :accept, :response_block, :status,
4
- :matcher, :content_type
4
+ :matcher, :content_type, :extension, :example_accept
5
5
 
6
- def initialize(action, accept: 'application/vnd.api+json', content_type: nil, status: nil, match: nil, cacheable: true, &block)
6
+ def initialize(action, accept: 'application/vnd.api+json', content_type: nil, status: nil, match: nil, cacheable: true, extension: nil, &block)
7
+ accept = MIME::Types.type_for("ex.#{extension}")[0]&.content_type if extension
8
+ @extension = extension.to_s if extension
7
9
  @action = action
8
10
  @response_block = block || proc {}
9
11
  @accept = accept unless match
12
+ @example_accept = accept
10
13
  @content_type = content_type || (@accept == '*/*' ? nil : @accept)
11
14
  @matcher = match || proc {}
12
15
  @status = status || 200
@@ -390,10 +390,10 @@
390
390
  <div class="col-xs-4 attribute-name">
391
391
  <strong><%= attribute.name %></strong>
392
392
  <i class="attribute-type"><%= attribute.type %></i>
393
- <% if attribute.required.present? %>
394
- <p class="optional">required: <%= attribute.required? %></p>
393
+ <% if attribute.required %>
394
+ <p class="optional">required: <%= attribute.required %></p>
395
395
  <% else %>
396
- <p class="optional">optional</p>
396
+ <p class="optional">optional</p>
397
397
  <% end %>
398
398
  </div>
399
399
  <div class="col-xs-8 attribute-description">
@@ -1,3 +1,3 @@
1
1
  module JSONAPIonify
2
- VERSION = "0.9.1"
2
+ VERSION = "0.9.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapionify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Waldrip
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-19 00:00:00.000000000 Z
11
+ date: 2016-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -503,12 +503,15 @@ files:
503
503
  - lib/jsonapionify.rb
504
504
  - lib/jsonapionify/api.rb
505
505
  - lib/jsonapionify/api/action.rb
506
+ - lib/jsonapionify/api/action/documentation.rb
507
+ - lib/jsonapionify/api/action/dummy.rb
506
508
  - lib/jsonapionify/api/attribute.rb
509
+ - lib/jsonapionify/api/attribute/documentation.rb
507
510
  - lib/jsonapionify/api/base.rb
508
511
  - lib/jsonapionify/api/base/app_builder.rb
509
512
  - lib/jsonapionify/api/base/class_methods.rb
510
513
  - lib/jsonapionify/api/base/delegation.rb
511
- - lib/jsonapionify/api/base/doc_helper.rb
514
+ - lib/jsonapionify/api/base/documentation.rb
512
515
  - lib/jsonapionify/api/base/reloader.rb
513
516
  - lib/jsonapionify/api/base/resource_definitions.rb
514
517
  - lib/jsonapionify/api/context.rb
@@ -519,6 +522,7 @@ files:
519
522
  - lib/jsonapionify/api/param_options.rb
520
523
  - lib/jsonapionify/api/relationship.rb
521
524
  - lib/jsonapionify/api/relationship/blocks.rb
525
+ - lib/jsonapionify/api/relationship/documentation.rb
522
526
  - lib/jsonapionify/api/relationship/many.rb
523
527
  - lib/jsonapionify/api/relationship/one.rb
524
528
  - lib/jsonapionify/api/resource.rb
@@ -546,6 +550,7 @@ files:
546
550
  - lib/jsonapionify/api/resource/definitions/response_headers.rb
547
551
  - lib/jsonapionify/api/resource/definitions/scopes.rb
548
552
  - lib/jsonapionify/api/resource/definitions/sorting.rb
553
+ - lib/jsonapionify/api/resource/documentation.rb
549
554
  - lib/jsonapionify/api/resource/error_handling.rb
550
555
  - lib/jsonapionify/api/resource/exec.rb
551
556
  - lib/jsonapionify/api/resource/includer.rb