jsonapionify 0.11.9 → 0.11.10

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
- Njg2MWVkODk4NWRkZjBlMTRjYzVhY2NjNzgwYzM3ZmFmNDU4NTVlZQ==
4
+ Nzg2ZGJhNjcxNmEzOTJmYWI4MjlkODQ5YjhhZWZkYWY5MjlkMTUyNQ==
5
5
  data.tar.gz: !binary |-
6
- NWFlZjllMzM3NmRhNDIzYjRmOTkxYzA0Yzg4ZDY3YmIxYzU0ZjE2OA==
6
+ YzE3OWY1MTA0ODhiZGZiNmZkMjcwYTZkMGRiZjFmY2ZlNjE0NmVhNQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- Zjg4Y2YzMGQ3YTMzYzZhNjE5YTM1NTRjZDMyODA3ZmVmNzA5ZGRkOTk3NWQ1
10
- YzQ2MGRjM2JjODMzMWUzZjRjZmJmZjk5MGJmMWMwNzJlZjkwYWU1OGQ2MzVj
11
- ZjA4NWU0NzU4MjJjZGIwNTFhMWU0MmJjZDUwNmRlMWIxYmZmODI=
9
+ ODE4MDFiZDFmOTlmNzBiOGU3ZDVlOTQ0YTE3NmMzYmU0Y2ZiM2EwNGIxMzcz
10
+ OTNlYWZlNDEzNmI5ZjBkNTdiNTBmNzNiYWIwZGUxNGMzZmJmNzE2NzQ1ZDc4
11
+ MzkyYTE3MWM4MDU5ODdkYmMwYjQ2ZWEyNTY5Yzc5ODU1MjgxZGY=
12
12
  data.tar.gz: !binary |-
13
- MDA1ZDA5ZGFkMjQyMWZhM2NjYzc2OTU5MTZhNDNjMTliZjU4Y2QwYTczYzU3
14
- ODhmNDI2OThkOTY0NmNiOTJhM2RjNmNhYTU1OTI0YWJiOTY2OTQ5YmZiYWQ1
15
- ZDNlNjI3YmVkMjhiZDI4ODk1ZTI1ZjYxMGFlZDQ2OTM1Zjk0Y2M=
13
+ ZmU0NjY3YzU0ZDUyZjA0ZDY1NWM2N2NhZjQyZWY4NmJlODQ3OTI1ZjBiYTJl
14
+ NjAwMjM3OTgyZDU0OGQwMDM4YzZjNjYyODEzMWU2MDA5N2YwMjYxZjMwNjUx
15
+ MDk5YWViNTIxZTBjZTE0NDdkZmM4NWMxMTEzYTJkNzY3MjQ4NjM=
data/README.md CHANGED
@@ -29,91 +29,200 @@ And then execute:
29
29
 
30
30
  ## Usage
31
31
 
32
- ### Context: Read First
32
+ ### APIs
33
33
 
34
- Before we get started with defining an API, you should understand a pattern used heavily throughout JSONAPIonify. This pattern is called a context. A context is a definition of data that is memoized and passed around a request. You may see context used as follows:
34
+ Api Definitions are the basis of JSONApi's DSL. They encompass resources that are available and can be run as standalone rack apps or be mounted within a rails app.
35
+
36
+ ```
37
+ class MyCompanyApi < JSONAPIonify::Base
38
+
39
+ # Write a description for your API.
40
+ description <<~markdown
41
+ A description of your API, that will be available at the top of the documentation.
42
+ markdown
43
+
44
+ # Add some rack middleware
45
+ use Rack::SSL::Enforcer
46
+
47
+ # Handle Authorization
48
+
49
+ end
50
+ ```
51
+
52
+ ### Resources
53
+
54
+ Resources are what the API serves. They usually link to models. Resources are defined by calling `.define_resource` on the class of a defined api.
35
55
 
36
56
  ```ruby
37
- before :create do |context|
38
- puts context.request.request_method
57
+ MyCompanyApi.define_resource :users do
58
+ # ... The resource definition
39
59
  end
40
60
  ```
41
61
 
42
- Contexts can also call other contexts within their definitions:
62
+ #### Scope
63
+ Each api uses a scope to determine how to look up objects the serve the request. By default the resource will look for a class that is similar to it's scope.
43
64
 
44
65
  ```ruby
45
- context :request_method do |context|
46
- context.request.request_method
66
+ MyCompanyApi.define_resource :users do
67
+ scope { Person }
47
68
  end
48
69
  ```
49
70
 
50
- JSONApionify already ships with a set of predefined contexts.
71
+ #### ID Attribute
72
+ JSONAPI needs an attribute to represent the object's id. This defaults to the `id` method, but can be overridden.
51
73
 
52
- ### Create an API
74
+ ```ruby
75
+ MyCompanyApi.define_resource :users do
76
+ id :key
77
+ end
78
+ ```
53
79
 
54
- Api Definitions are the basis of JSONApi's DSL. They encompass resources that are available and can be run as standalone rack apps or be mounted within a rails app.
80
+ #### Instance Lookup
81
+ In order to locate an instance in the defined scope, the resource needs a instructions to do so. If the scope is a descendant of `ActiveRecord::Base`, it will automatically use `scope.find(id)` for the lookup.
55
82
 
83
+ ```ruby
84
+ MyCompanyApi.define_resource :users do
85
+ instance { |scope, id| scope.find_by key: id }
86
+ end
56
87
  ```
57
- class MyCompanyApi < JSONAPIonify::Base
58
88
 
59
- # Write a description for your API.
60
- description <<~markdown
61
- A description of your API, that will be available at the top of the documentation.
62
- markdown
63
-
64
- # Add some rack middleware
65
- use Rack::SSL::Enforcer
66
-
67
- # Handle Authorization
89
+ #### Instance Builder
90
+ When creating an instance, the resource needs to know how to build a new object. If the scope is a descendant of `ActiveRecord::Base`, it will automatically use `scope.new` to build the object.
68
91
 
92
+ #### Contexts
93
+ Contexts are memoized blocks of code that are used throughout the request lifecycle of a resource. They can be referenced in [`hooks`](#hooks), [`actions`](#hooks), [`attributes`](#attributes), other [`contexts`](#contexts), etc. A context is defined as follows:
94
+
95
+ ```ruby
96
+ MyCompanyApi.define_resource :users do
97
+ context :request_method do |context|
98
+ context.request.request_method
99
+ end
69
100
  end
70
101
  ```
71
102
 
72
- ### Predefined Contexts
103
+ > **NOTE:** The gem ships with [predefined contexts](#predefined-contexts).
104
+
105
+ #### Attributes
106
+ Attributes define what fields will appear in the response. Attribute definitions require a name, a type, and a description. In addition, the attribute may include a block that defines how the value is resolved.
107
+
108
+ ```ruby
109
+ MyCompanyApi.define_resource :users do
110
+ attribute :name, types.String, 'the users name' do |attr_name, instance, context| do
111
+ instance.public_send(attr_name)
112
+ end
113
+ end
114
+ ```
115
+
116
+ ##### Attribute types
117
+ Attributes require a type that map to JSON types. They are as follows:
118
+ `types.String`, `types.Boolean`, `types.Integer`, `types.Float`, `types.Array(of: ?)`, `types.Object`
119
+
120
+ > Array types take an `of` keyword of another type.
73
121
 
74
- #### request_body
75
- The raw body of the request
122
+ #### Relationships
123
+ Relationships define the way resources reference each other. There are two types of relationships. Relationships behave just like the resource they represent except it's scoped to the parent object. By default the scope of of a relationship resolves to a method equal to the name of the relationship. This can be overridden by passing a `Proc` to the resolve keyword. In addition, the default resource the object resolves to can be specified with the `resource` keyword. If a relationship is given a block it is treated the same as a resource definition, but it's [actions](#actions) are limited by the type of the relationship.
76
124
 
77
- #### request_object
78
- The JSON parsed into a JSONApionify Structure Object. Keys can be accessed as symbols.
125
+ ##### One-to-One
126
+ One-to-One relationships allow a parent resource to reference a single instance of another resource. It is defined as follows:
79
127
 
80
- #### id
81
- The id present in the request path, if present.
128
+ ```ruby
129
+ MyCompanyApi.define_resource :users do
130
+ relates_to_one :thing, resolve: proc { |rel, instance, context| instance.public_send(rel) } do
131
+ replace
132
+ end
133
+ end
134
+ ```
135
+
136
+ ##### One-to-Many
137
+ One-to-One relationships allow a parent resource to reference a collection of another resource. It is defined as follows:
138
+
139
+ ```ruby
140
+ MyCompanyApi.define_resource :users do
141
+ relates_to_many :friends, resource: :users, resolve: proc { |rel, instance, context| instance.public_send(rel) } do
142
+ add
143
+ replace
144
+ remove
145
+ end
146
+ end
147
+ ```
82
148
 
83
- #### request_id
84
- The id of the requested resource, within the data attribute of the request object.
149
+ #### Actions
150
+ Actions define the routes of a resource and what processing happens when that route is called.
85
151
 
86
- #### request_attributes
87
- The parsed attributes from the request object. Accessing this context, will also validate the data/structure.
152
+ **Root level resources have the following actions:**
88
153
 
89
- #### request_relationships
90
- The parsed relationships from the request object. Accessing this context, will also validate the data/structure.
154
+ | Action | Path
155
+ |--------|-----
156
+ | List | `GET /{resource}`
157
+ | Create | `POST /{resource}`
158
+ | Read | `GET /{resource}/{id}`
159
+ | Update | `PATCH /{resource}/{id}`
160
+ | Delete | `DELETE /{resource}/{id}`
91
161
 
92
- #### request_instance
93
- The instance of the object found from the request's data/type and data/id attibutes. This is determined from the resource's defined scope.
162
+ **One-to-Many relationships resources have the following actions:**
94
163
 
95
- #### request_resource
96
- The resource's scope determined from the request's data/type attribute.
164
+ | Action | Path
165
+ |--------|-----
166
+ | List | `GET /{resource}/{id}/{relationship}`
167
+ | Create | `POST /{resource}/{id}/{relationship}`
168
+ | Show | `GET /{resource}/{id}/relationships/{relationship}`
169
+ | Add | `POST /{resource}/{id}/relationships/{relationship}`
170
+ | Remove | `DELETE /{resource}/{id}/relationships/{relationship}`
171
+ | Replace| `PATCH /{resource}/{id}/relationships/{relationship}`
97
172
 
98
- #### request_data
99
- The data attribute in the top level object of the request
173
+ **One-to-One relationships resources have the following actions:**
100
174
 
101
- #### authentication
102
- An object containing the authentication data.
175
+ | Action | Path
176
+ |--------|-----
177
+ | Read | `GET /{resource}/{id}/{relationship}`
178
+ | Show | `GET /{resource}/{id}/relationships/{relationship}`
179
+ | Replace| `PATCH /{resource}/{id}/relationships/{relationship}`
103
180
 
104
- #### links
105
- The links object that will be present in the response.
181
+ #### Hooks
182
+ Hooks can be invoked throughout the request lifecycle. They are defined in the following order:
106
183
 
107
- #### meta
108
- The meta object that will be present in the response.
184
+ ```
185
+ before_request
186
+ before_{action}
187
+ before_commit_{action}
188
+ [commit action]
189
+ after_commit_{action}
190
+ before_response
191
+ [response]
192
+ after_response
193
+ after_{action}
194
+ after_request
195
+ ```
109
196
 
110
- #### response_object
111
- The jsonapi object that will be used for the response.
197
+ A hook can be defined on a resource with:
112
198
 
113
- #### response_collection
114
- The response for the collection.
199
+ ```ruby
200
+ MyCompanyApi.define_resource :users do
201
+ before :create do |context|
202
+ puts context.request.request_method
203
+ end
204
+ end
205
+ ```
115
206
 
207
+ ### Predefined Contexts
116
208
 
209
+ | Context | Description
210
+ |--------- |----------
211
+ | `request` | The request.
212
+ | `request_body` | The raw body of the request.
213
+ | `request_object` | The JSON parsed into a JSONApionify Structure Object. Keys can be accessed as symbols.
214
+ | `id` | The id present in the request path, if present.
215
+ | `request_id` | The id of the requested resource, within the data attribute of the request object.
216
+ | `request_attributes` | The parsed attributes from the request object. Accessing this context, will also validate the data/structure.
217
+ | `request_relationships` | The parsed relationships from the request object. Accessing this context, will also validate the data/structure.
218
+ | `request_instance` | The instance of the object found from the request's data/type and data/id attributes. This is determined from the resource's defined scope.
219
+ | `request_resource` | The resource's scope determined from the request's data/type attribute.
220
+ | `request_data` | The data attribute in the top level object of the request
221
+ | `authentication` | An object containing the authentication data.
222
+ | `links` | The links object that will be present in the response.
223
+ | `meta` | The meta object that will be present in the response.
224
+ | `response_object` | The jsonapi object that will be used for the response.
225
+ | `response_collection` | The response for the collection.
117
226
 
118
227
  ## Development
119
228
 
@@ -5,7 +5,7 @@ module JSONAPIonify::Api
5
5
  id :id
6
6
  scope { self.type.classify.constantize }
7
7
  collection do |scope, context|
8
- if defined?(ActiveRecord) && scope < ActiveRecord::Base && scope.is_a?(Class)
8
+ if defined?(ActiveRecord) && scope.is_a?(Class) && scope < ActiveRecord::Base
9
9
  scope.all
10
10
  else
11
11
  scope
@@ -13,7 +13,7 @@ module JSONAPIonify::Api
13
13
  end
14
14
 
15
15
  instance do |scope, key|
16
- if defined?(ActiveRecord) && scope < ActiveRecord::Base
16
+ if defined?(ActiveRecord) && scope.is_a?(Class) && scope < ActiveRecord::Base
17
17
  scope.find_by! id_attribute => key
18
18
  else
19
19
  raise NotImplementedError, 'instance not implemented'
@@ -21,7 +21,7 @@ module JSONAPIonify::Api
21
21
  end
22
22
 
23
23
  new_instance do |scope|
24
- if defined?(ActiveRecord) && scope < ActiveRecord::Base
24
+ if defined?(ActiveRecord) && scope.is_a?(Class) && scope < ActiveRecord::Base
25
25
  scope.new
26
26
  else
27
27
  raise NotImplementedError, 'scope not implemented'
@@ -7,7 +7,7 @@ module JSONAPIonify::Api
7
7
  included do
8
8
  before :list, :create, :read, :update do |context|
9
9
  supports_includes = context.root_request? && context.includes.present?
10
- is_active_record = defined?(ActiveRecord) && context.scope.respond_to?(:<) && context.scope < ActiveRecord::Base
10
+ is_active_record = defined?(ActiveRecord) && context.scope.is_a?(Class) && context.scope < ActiveRecord::Base
11
11
  if supports_includes && is_active_record
12
12
  valid_includes = context.includes.select do |k, v|
13
13
  context.scope._reflect_on_association(k)
@@ -1,3 +1,3 @@
1
1
  module JSONAPIonify
2
- VERSION = "0.11.9"
2
+ VERSION = "0.11.10"
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.11.9
4
+ version: 0.11.10
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-06-15 00:00:00.000000000 Z
11
+ date: 2016-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport