api_presenter 0.4.1 → 1.0.0
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 +5 -5
- data/.travis.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/README.md +30 -32
- data/api_presenter.gemspec +1 -1
- data/lib/api_presenter/base.rb +2 -2
- data/lib/api_presenter/version.rb +1 -1
- metadata +8 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b9b45f72f53a0f0d6ddf34ba993ec0a6f5cbcd6fd7f2b8b2436d5963d2f50296
|
4
|
+
data.tar.gz: 48d1037e5b1af28c574b421996e9350e119fddc89024aeb7bbb7b059f9cec8e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 696d7eb80f9327f58f44ab02adfdc14da7a204fa4ae18ac360bde122f5953b55fc986cfa8489fa69c0f4372f3de1d525047512b3e4344b68e35fe3e1fb0f8c54
|
7
|
+
data.tar.gz: 1df07f9a061b26b111c00ce52b57a6f89911b914fd787e9e008254da9bf5d01c350ea29af57ea948dd5836b6e2723d979ab946053fd842fb973cbe6c574022e5
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
# ApiPresenter
|
2
2
|
|
3
|
-
|
3
|
+
REST APIs provide a concise and conventional means of retrieving resources for a client. But in the real world, clients often have additional data requirements beyond the specifically requested resource(s):
|
4
4
|
|
5
|
-
|
5
|
+
1. Current user permissions for the returned records, so that the client can intelligently draw its UI (ex: edit/delete buttons).
|
6
|
+
2. Associated data, to mitigate total number of requests (ex: return authors with posts).
|
6
7
|
|
7
|
-
|
8
|
-
* Allow inclusion of associated data to mitigate total number of requests
|
9
|
-
|
10
|
-
ApiPresenter does both of these things, plus a bit more.
|
8
|
+
ApiPresenter provides both of these things, plus a bit more.
|
11
9
|
|
12
10
|
## Installation
|
13
11
|
|
@@ -27,7 +25,7 @@ Or install it yourself as:
|
|
27
25
|
|
28
26
|
## Usage
|
29
27
|
|
30
|
-
We'll use a
|
28
|
+
ApiPresenter is well suited to large, relational systems. We'll use a blog as the usage example for this gem. The blog has the following model structure:
|
31
29
|
|
32
30
|
```ruby
|
33
31
|
class Category < ActiveRecord::Base
|
@@ -52,22 +50,22 @@ class User < ActiveRecord::Base
|
|
52
50
|
end
|
53
51
|
```
|
54
52
|
|
55
|
-
|
53
|
+
Usage examples will be in the context of requesting posts as the primary collection.
|
56
54
|
|
57
55
|
### 0. Generate config file
|
58
56
|
|
59
57
|
`rails g api_presenter:config`
|
60
58
|
|
61
|
-
|
59
|
+
Generate your configuration file. Currently, ApiPresenter allows customization of querystring parameter names for including policies and associated resources (see below). More configuration options to come.
|
62
60
|
|
63
61
|
### 1. Create your Presenter
|
64
62
|
|
65
|
-
|
63
|
+
Generate a presenter class for your ActiveRecord model. The generator will also ensure the presence of an `ApplicationApiPresenter` base class for centralized methods.
|
66
64
|
|
67
65
|
`rails g api_presenter:presenter post`
|
68
66
|
|
69
67
|
```ruby
|
70
|
-
class PostPresenter <
|
68
|
+
class PostPresenter < ApplicationApiPresenter
|
71
69
|
def associations_map
|
72
70
|
{
|
73
71
|
categories: { associations: { sub_category: :category } },
|
@@ -86,21 +84,15 @@ class PostPresenter < ApiApplicationController
|
|
86
84
|
end
|
87
85
|
```
|
88
86
|
|
89
|
-
Presenters
|
87
|
+
Presenters can define three opt-in methods:
|
90
88
|
|
91
|
-
* `associations_map`
|
89
|
+
* `associations_map` Associated resources that you would like to be includable with the primary collection. Consists of the model name as key and the traversal required to preload/load them. In most cases, the value of `associations` will correspond directly to associations on the primary model.
|
92
90
|
* `policy_methods` A list of Pundit policy methods to resolve for the primary collection if policies are requested.
|
93
|
-
* `policy_associations` Additional
|
91
|
+
* `policy_associations` Additional associations to preload in order to optimize policies that must traverse asscoiations.
|
94
92
|
|
95
93
|
### 2. Enable your controllers
|
96
94
|
|
97
|
-
|
98
|
-
|
99
|
-
The following configurable querystring params are used by the supplied controller concern's `present` method:
|
100
|
-
|
101
|
-
* `count [Boolean]` Pass true if you just want a count of the primary collection
|
102
|
-
* `policies [Boolean]` Pass true if you want to resolve policies for the primary collection records
|
103
|
-
* `include [String, Array]` A comma-delimited list or array of collection names (camelCase or under_scored) to include with the primary collection
|
95
|
+
Include the supplied controller concern at your `ApplicationController` level, or on a specific controller. This concern provides the `present` method, which can be called on an `ActiveRecord::Relation`, an array of records, or even a single record (preloading of associated collections is only performed for relations).
|
104
96
|
|
105
97
|
```ruby
|
106
98
|
class ApplicationController
|
@@ -129,17 +121,25 @@ class PostsController < ApplicationController
|
|
129
121
|
end
|
130
122
|
```
|
131
123
|
|
124
|
+
Controller params are used to tell the presenter what to load. The default param keys are `count`, `policies`, and `include`:
|
125
|
+
|
126
|
+
* `count [Boolean]` Pass true if you just want a count of the primary collection.
|
127
|
+
* `policies [Boolean]` Pass true if you want to resolve policies for the primary collection.
|
128
|
+
* `include [String, Array]` A comma-delimited list or array of collection names (camelCase or under_scored) to include with the primary collection.
|
129
|
+
|
132
130
|
### 3. Render the result
|
133
131
|
|
134
|
-
|
132
|
+
After calling the `present` method in a controller action, you access your processed collection through the `@presenter` instance variable. How you ultimately render the data produced by ApiPresenter is up to you.
|
133
|
+
|
134
|
+
`@presenter` has the following properties:
|
135
135
|
|
136
136
|
* `collection [Array<ActiveRecord::Base>]` The primary collection that was passed into the presenter. Empty if count requested.
|
137
137
|
* `total_count [Integer]` When using Kaminari or another pagination method that defines a `total_count` property, returns unpaginated count. If the primary collection is not an `ActiveRecord::Relation`, simply returns the number of records.
|
138
|
-
* `included_collection_names [Array<Symbol>]` Convenience method that returns an array of included
|
138
|
+
* `included_collection_names [Array<Symbol>]` Convenience method that returns an array of included collection model names.
|
139
139
|
* `included_collections [Hash]` A hash of included collections, consisting of the model name and corresponding records.
|
140
140
|
* `policies [Array<Hash>]` An array of resolved policies for the primary collection.
|
141
141
|
|
142
|
-
Here's an example of how you might render
|
142
|
+
Here's an example of how you might render your data using JBduiler:
|
143
143
|
|
144
144
|
### api/posts/index.json.jbuilder
|
145
145
|
|
@@ -176,7 +176,7 @@ end
|
|
176
176
|
|
177
177
|
### 4. Output
|
178
178
|
|
179
|
-
Using the code above, our call to `GET /posts` would result in the following JSON:
|
179
|
+
Using the code above, our call to `GET /posts?include=categories,subCategories,users&policies=true` would result in the following JSON:
|
180
180
|
|
181
181
|
```json
|
182
182
|
{
|
@@ -206,7 +206,7 @@ Using the code above, our call to `GET /posts` would result in the following JSO
|
|
206
206
|
}
|
207
207
|
```
|
208
208
|
|
209
|
-
And similarily, for `GET /posts/1`:
|
209
|
+
And similarily, for `GET /posts/1?include=categories,subCategories,users&policies=true`:
|
210
210
|
|
211
211
|
```json
|
212
212
|
{
|
@@ -234,12 +234,12 @@ And similarily, for `GET /posts/1`:
|
|
234
234
|
|
235
235
|
### Conditional includes
|
236
236
|
|
237
|
-
There are a number of ways you can conditionally include resources, depending, for
|
237
|
+
There are a number of ways you can conditionally include resources, depending, for instance, on user type.
|
238
238
|
|
239
239
|
#### Add conditions inside `associations_map` method
|
240
240
|
|
241
241
|
```ruby
|
242
|
-
class PostPresenter <
|
242
|
+
class PostPresenter < ApiApplicationPresenter
|
243
243
|
def associations_map
|
244
244
|
current_user.admin? ? admin_associations_map : user_associations_map
|
245
245
|
end
|
@@ -265,7 +265,7 @@ end
|
|
265
265
|
|
266
266
|
#### Use `condition` property within `association_map` definition
|
267
267
|
|
268
|
-
Via inline string
|
268
|
+
##### Via inline string
|
269
269
|
|
270
270
|
```ruby
|
271
271
|
class PostPresenter < ApiPresenter::Base
|
@@ -279,7 +279,7 @@ class PostPresenter < ApiPresenter::Base
|
|
279
279
|
end
|
280
280
|
```
|
281
281
|
|
282
|
-
Via method call
|
282
|
+
##### Via method call
|
283
283
|
|
284
284
|
```ruby
|
285
285
|
class PostPresenter < ApiPresenter::Base
|
@@ -311,12 +311,10 @@ end
|
|
311
311
|
|
312
312
|
## TODO
|
313
313
|
|
314
|
-
* More doc
|
315
314
|
* Decouple from Pundit
|
316
315
|
* Make index policy checking on includes optional
|
317
316
|
* Allow custom collection names
|
318
317
|
* Add test helper to assert presenter was called for a given controller action
|
319
|
-
* Add presenter generator
|
320
318
|
|
321
319
|
## Development
|
322
320
|
|
data/api_presenter.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.add_dependency "activesupport", ">= 3.0.0"
|
20
20
|
spec.add_dependency "pundit"
|
21
21
|
spec.add_development_dependency "activerecord", ">= 4.2.3"
|
22
|
-
spec.add_development_dependency "bundler", "~>
|
22
|
+
spec.add_development_dependency "bundler", "~> 2.2.12"
|
23
23
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
24
|
spec.add_development_dependency "rspec"
|
25
25
|
spec.add_development_dependency "sqlite3"
|
data/lib/api_presenter/base.rb
CHANGED
@@ -14,8 +14,8 @@ module ApiPresenter
|
|
14
14
|
#
|
15
15
|
# @return [ApiPresenter::Base]
|
16
16
|
#
|
17
|
-
def self.call(
|
18
|
-
new(
|
17
|
+
def self.call(current_user: nil, relation:, params: {})
|
18
|
+
new(current_user: current_user, relation: relation, params: params).call
|
19
19
|
end
|
20
20
|
|
21
21
|
# @param current_user [User] Optional. current_user context.
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_presenter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuval Kordov
|
8
8
|
- Little Blimp
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-06-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -59,14 +59,14 @@ dependencies:
|
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
62
|
+
version: 2.2.12
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: 2.2.12
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rake
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -148,7 +148,7 @@ homepage: http://github.com/uberllama/api_presenter
|
|
148
148
|
licenses:
|
149
149
|
- MIT
|
150
150
|
metadata: {}
|
151
|
-
post_install_message:
|
151
|
+
post_install_message:
|
152
152
|
rdoc_options: []
|
153
153
|
require_paths:
|
154
154
|
- lib
|
@@ -163,9 +163,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
163
|
- !ruby/object:Gem::Version
|
164
164
|
version: '0'
|
165
165
|
requirements: []
|
166
|
-
|
167
|
-
|
168
|
-
signing_key:
|
166
|
+
rubygems_version: 3.0.9
|
167
|
+
signing_key:
|
169
168
|
specification_version: 4
|
170
169
|
summary: Return associations and policies with API responses
|
171
170
|
test_files: []
|