jsonapionify 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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