api_presenter 0.2.4 → 0.3.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
  SHA1:
3
- metadata.gz: 2a3e0a34d5d50f902760195ffd58a409d3231a15
4
- data.tar.gz: 8a4261472f7ba030c7ff72e2bed5d9c3171b98d6
3
+ metadata.gz: 9e411385a8bd85df6bc3efe9f1ec418d5608f26f
4
+ data.tar.gz: a7da14574b9aabd4501edafd1555feb16246ff05
5
5
  SHA512:
6
- metadata.gz: 3e3491e2c26ac8affb10ba11eaeef277be47b4b9666f205a6c9f5a07da5178b204ffcc28961e10df10811abb6a98ff5cc0e0968e0d213911f07f96d1094a94fa
7
- data.tar.gz: e426cce2a716fc7cdcb4e5066cd9b9a51509a5c339886031c27159fe0a6698c07f08f107f939cd6c0a071637bd7f4ee942f61e2876d139757f42383e157ed367
6
+ metadata.gz: 810bfdd0b1932949b0d6984ac1b0935467de3e5d27858f05890b906447aa2124fc0beee23c0cf95a5d624df168a2e20eb2b38d567650c685e291a905724859a4
7
+ data.tar.gz: 29e3508ed61708ae44f7f4470e9687a0131d0e56a991b307ba1519ebd6b6755d92ff7903a26f7af6d25b6bd78d8f62b4a742332439d5b9b758f6bfc08e65f583
data/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  A much longer readme is coming, including best practices and cautions, but in the meantime lets keep it simple...
4
4
 
5
- When creating RESTful APIs for web or mobile clients, there are a couple of common use cases that have emerged:
5
+ When creating RESTful APIs for web or mobile clients, there are a couple of desirable endpoint behaviors:
6
6
 
7
- * Allow inclusion of associated data to mitigate number of requests
8
7
  * Include permissions so that the client can intelligently draw its UI (ex: edit/delete buttons), while maintaining a single source of truth
8
+ * Allow inclusion of associated data to mitigate total number of requests
9
9
 
10
10
  ApiPresenter does both of these things, plus a bit more.
11
11
 
@@ -52,7 +52,11 @@ class User < ActiveRecord::Base
52
52
  end
53
53
  ```
54
54
 
55
- When clients request posts (the primary collection), they may want any or all of the above data for those posts.
55
+ ### 0. Generate config file
56
+
57
+ `rails g api_presenter:config`
58
+
59
+ Generates a configuration file that allows you to override the default querystring params used by the `presenter` concern. More to come.
56
60
 
57
61
  ### 1. Create your Presenter
58
62
 
@@ -78,13 +82,19 @@ end
78
82
 
79
83
  Presenters can define up to three methods:
80
84
 
81
- * `associations_map` The includable resources for the ActiveRecord model (`Post`, in this case). Consists of the model name as key and traversal required to preload/load them. In most cases, the value of `associations` will correspond directly to associations on the primary model.
82
- * `policy_methods` A list of Pundit policy methods to resolve for the primary collection.
85
+ * `associations_map` The business-dictated includable resources for the ActiveRecord model (`Post`, in this case). Consists of the model name as key and traversal required to preload/load them. In most cases, the value of `associations` will correspond directly to associations on the primary model.
86
+ * `policy_methods` A list of Pundit policy methods to resolve for the primary collection if policies are requested.
83
87
  * `policy_associations` Additional records to preload in order to optimize policies that must traverse asscoiations.
84
88
 
85
89
  ### 2. Enable your controllers
86
90
 
87
- Your presentable collection can be an `ActiveRecord::Relation`, an array of records, or even a single record. Just call `present` on it. The preloads will be performed, and the included collections/policies will be available in the `@presenter` instance variable.
91
+ Your presentable collection can be an `ActiveRecord::Relation`, an array of records, or even a single record. Just call `present` on it from your controller action. The preloads will be performed, and the included collections/policies will be available in the `@presenter` instance variable.
92
+
93
+ The following querystring params are used by the supplied controller concern's `present` method:
94
+
95
+ * `count [Boolean]` Pass true if you just want a count of the primary collection
96
+ * `policies [Boolean]` Pass true if you want to resolve policies for the primary collection records
97
+ * `include [String, Array]` A comma-delimited list or array of collection names (camelCase or under_scored) to include with the primary collection
88
98
 
89
99
  ```ruby
90
100
  class ApplicationController
@@ -92,11 +102,18 @@ class ApplicationController
92
102
  end
93
103
 
94
104
  class PostsController < ApplicationController
105
+
106
+ # @example
107
+ # GET /posts?include=categories,subCategories,users&policies=true
108
+ #
95
109
  def index
96
110
  posts = PostQuery.records(current_user, params)
97
111
  present posts
98
112
  end
99
113
 
114
+ # @example
115
+ # GET /posts/:id?include=categories,subCategories,users&policies=true
116
+ #
100
117
  def show
101
118
  post = Post.find(params[:id])
102
119
  present post
@@ -134,13 +151,6 @@ end
134
151
  json.partial!("api/shared/included_collections_and_meta", presenter: @presenter)
135
152
  ```
136
153
 
137
- ```ruby
138
- json.posts(@presenter.collection) do |post|
139
- json.partial!(post)
140
- end
141
- json.partial!("api/shared/included_collections_and_meta", presenter: @presenter)
142
- ```
143
-
144
154
  ### api/shared/included_collections_and_meta
145
155
 
146
156
  ```ruby
@@ -156,6 +166,62 @@ json.meta do
156
166
  end
157
167
  ```
158
168
 
169
+ ### 4. Output
170
+
171
+ Using the code above, our call to `GET /posts` would result in the following JSON:
172
+
173
+ ```json
174
+ {
175
+ "posts": [
176
+ { "id": 1, "sub_category": 1, "creator_id": 1, "publisher_id": 2, "body": "Lorem dim sum", "published": true },
177
+ { "id": 2, "sub_category": 2, "creator_id": 3, "publisher_id": null, "body": "Lorem dim sum", "published": false }
178
+ ],
179
+ "categories": [
180
+ { "id": 1, "name": "Animals" }
181
+ ],
182
+ "sub_categories": [
183
+ { "id": 1, "category_id": 1, "name": "Lemurs" },
184
+ { "id": 2, "category_id": 1, "name": "Anteaters" }
185
+ ],
186
+ "users": [
187
+ { "id": 1, "name": "Dora" },
188
+ { "id": 2, "name": "Boots" },
189
+ { "id": 3, "name": "Backpack" }
190
+ ],
191
+ "meta": {
192
+ "total_count": 2,
193
+ "policies": [
194
+ { "post_id": 1, "update": true, "destroy": false },
195
+ { "post_id": 2, "update": true, "destroy": true }
196
+ ]
197
+ }
198
+ }
199
+ ```
200
+
201
+ And similarily, for `GET /posts/1`:
202
+
203
+ ```json
204
+ {
205
+ "post": { "id": 1, "sub_category": 1, "creator_id": 1, "publisher_id": 2, "body": "Lorem dim sum", "published": true },
206
+ "categories": [
207
+ { "id": 1, "name": "Animals" }
208
+ ],
209
+ "sub_categories": [
210
+ { "id": 1, "category_id": 1, "name": "Lemurs" }
211
+ ],
212
+ "users": [
213
+ { "id": 1, "name": "Dora" },
214
+ { "id": 2, "name": "Boots" }
215
+ ],
216
+ "meta": {
217
+ "total_count": 1,
218
+ "policies": [
219
+ { "post_id": 1, "update": true, "destroy": false }
220
+ ]
221
+ }
222
+ }
223
+ ```
224
+
159
225
  ## Advanced Usage
160
226
 
161
227
  ### Conditional includes
@@ -242,6 +308,7 @@ end
242
308
  * Make index policy checking on includes optional
243
309
  * Allow custom collection names
244
310
  * Add test helper to assert presenter was called for a given controller action
311
+ * Add presenter generator
245
312
 
246
313
  ## Development
247
314
 
data/lib/api_presenter.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  require 'pundit'
2
+
2
3
  module ApiPresenter; end
3
4
 
4
5
  require 'api_presenter/base'
6
+ require 'api_presenter/configuration'
5
7
  require 'api_presenter/concerns/presentable'
6
8
  require 'api_presenter/parsers/parse_include_params'
7
9
  require 'api_presenter/resolvers/base'
@@ -80,7 +80,7 @@ module ApiPresenter
80
80
  # @return [Array<Symbol>]
81
81
  #
82
82
  def included_collection_names
83
- @included_collection_names ||= Parsers::ParseIncludeParams.call(params[:include])
83
+ @included_collection_names ||= Parsers::ParseIncludeParams.call(params[ApiPresenter.configuration.include_param])
84
84
  end
85
85
 
86
86
  # Map of included collection names and loaded record
@@ -172,11 +172,11 @@ module ApiPresenter
172
172
  private
173
173
 
174
174
  def count_only?
175
- @count_only ||= !!params[:count]
175
+ @count_only ||= !!params[ApiPresenter.configuration.count_param]
176
176
  end
177
177
 
178
178
  def resolve_policies?
179
- @resolve_policies ||= current_user && !!params[:policies]
179
+ @resolve_policies ||= current_user && !!params[ApiPresenter.configuration.policies_param]
180
180
  end
181
181
 
182
182
  def resolve_included_collctions?
@@ -0,0 +1,43 @@
1
+ module ApiPresenter
2
+ class Configuration
3
+ # Querystring param key that determines whether or not to just produce a total count
4
+ #
5
+ # @return [Symbol]
6
+ #
7
+ attr_accessor :count_param
8
+
9
+ # Querystring param key containing the included collection names
10
+ #
11
+ # @return [Symbol]
12
+ #
13
+ attr_accessor :include_param
14
+
15
+ # Querystring param key that determines whether or not to resolve policies for primary collection
16
+ #
17
+ # @return [Symbol]
18
+ #
19
+ attr_accessor :policies_param
20
+
21
+ def initialize
22
+ @count_param = :count
23
+ @include_param = :include
24
+ @policies_param = :policies
25
+ end
26
+ end
27
+
28
+ # @return [ApiPresenter::Configuration] ApiPresenter's current configuration
29
+ def self.configuration
30
+ @configuration ||= Configuration.new
31
+ end
32
+
33
+ # Set ApiPresenter configuration
34
+ #
35
+ # @example
36
+ # ApiPresenter.configure do |config|
37
+ # config.include_param = :includes
38
+ # end
39
+ #
40
+ def self.configure
41
+ yield configuration
42
+ end
43
+ end
@@ -1,3 +1,3 @@
1
1
  module ApiPresenter
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1 @@
1
+ Creates configuration file
@@ -0,0 +1,11 @@
1
+ module ApiPresenter
2
+ module Generators
3
+ class ConfigGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def copy_config_file
7
+ copy_file 'api_presenter_config.rb', 'config/initializers/api_presenter_config.rb'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ ApiPresenter.configure do |config|
2
+ # config.count_param = :count
3
+ # config.include_param = :include
4
+ # config.policies_param = :policies
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuval Kordov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2016-11-07 00:00:00.000000000 Z
12
+ date: 2016-11-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -131,11 +131,15 @@ files:
131
131
  - lib/api_presenter.rb
132
132
  - lib/api_presenter/base.rb
133
133
  - lib/api_presenter/concerns/presentable.rb
134
+ - lib/api_presenter/configuration.rb
134
135
  - lib/api_presenter/parsers/parse_include_params.rb
135
136
  - lib/api_presenter/resolvers/base.rb
136
137
  - lib/api_presenter/resolvers/included_collections_resolver.rb
137
138
  - lib/api_presenter/resolvers/policies_resolver.rb
138
139
  - lib/api_presenter/version.rb
140
+ - lib/generators/api_presenter/config/USAGE
141
+ - lib/generators/api_presenter/config/config_generator.rb
142
+ - lib/generators/api_presenter/config/templates/api_presenter_config.rb
139
143
  homepage: http://github.com/uberllama/api_presenter
140
144
  licenses:
141
145
  - MIT