pragma-decorator 0.1.0 → 1.0.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: 7fbddf33eb638f9dc7cc36f989bc22ffea969ee5
4
- data.tar.gz: 363a2780b6a8316b3330eb7756f1cda1e5a768cf
3
+ metadata.gz: 1ff48d9c11a4d5a07d7a11f0b8c90005a06ff998
4
+ data.tar.gz: 53f69d42826745d481a7dc0317e28e90be17904e
5
5
  SHA512:
6
- metadata.gz: 34b21171d3f3961379083f634e2178d6b6166d7c75b0d5c50ddb6a5a6ac75390728988beaeb4a31a7ca1a9c45f0436ea32809d84ab13fd015a3866c9323054b6
7
- data.tar.gz: 1f5a2172ef77a3261676d119deb273bd9b75962db264a3787fa0f3feb600390ac3fb9d280d226e2bc83919075f66eb82ce1ab9ce03f5ef38db044bd195a62aeb
6
+ metadata.gz: cf5197a94d5f7664b8ed594687c5d549abf3c01a9f61166a68c8a93dbd89bf4ade857efd1568b0e6645f9ec3f2396434eb56045805b977cdb9a38d8f4783f58e
7
+ data.tar.gz: 37bea54b8e417195fccfb37cfda43635bd625570f8569afa5cb68fc7de70b5652e7d1834f0e30f480a7709fdf2e6c430b13d214699391bf8137364bdce140769
data/.gitignore CHANGED
@@ -3,7 +3,6 @@
3
3
  /Gemfile.lock
4
4
  /_yardoc/
5
5
  /coverage/
6
- /doc/
7
6
  /pkg/
8
7
  /spec/reports/
9
8
  /tmp/
data/README.md CHANGED
@@ -32,216 +32,7 @@ $ gem install pragma-decorator
32
32
 
33
33
  ## Usage
34
34
 
35
- Creating a decorator is as simple as inheriting from `Pragma::Decorator::Base`:
36
-
37
- ```ruby
38
- module API
39
- module V1
40
- module User
41
- module Decorator
42
- class Resource < Pragma::Decorator::Base
43
- property :id
44
- property :email
45
- property :full_name
46
- end
47
- end
48
- end
49
- end
50
- end
51
- ```
52
-
53
- Just instantiate the decorator by passing it an object to decorate, then call `#to_hash` or
54
- `#to_json`:
55
-
56
- ```ruby
57
- decorator = API::V1::User::Decorator::Resource.new(user)
58
- decorator.to_json
59
- ```
60
-
61
- This will produce the following JSON:
62
-
63
- ```json
64
- {
65
- "id": 1,
66
- "email": "jdoe@example.com",
67
- "full_name": "John Doe"
68
- }
69
- ```
70
-
71
- Since Pragma::Decorator is built on top of [ROAR](https://github.com/apotonick/roar) (which, in
72
- turn, is built on top of [Representable](https://github.com/apotonick/representable)), you should
73
- consult their documentation for the basic usage of decorators; the rest of this section only covers
74
- the features provided specifically by Pragma::Decorator.
75
-
76
- ### Object types
77
-
78
- It is recommended that decorators expose the type of the decorated object. You can achieve this
79
- with the `Type` mixin:
80
-
81
- ```ruby
82
- module API
83
- module V1
84
- module User
85
- module Decorator
86
- class Resource < Pragma::Decorator::Base
87
- feature Pragma::Decorator::Type
88
- end
89
- end
90
- end
91
- end
92
- end
93
- ```
94
-
95
- This would result in the following representation:
96
-
97
- ```json
98
- {
99
- "type": "user",
100
- "...": "...""
101
- }
102
- ```
103
-
104
- You can also set a custom type name (just make sure to use it consistently!):
105
-
106
- ```ruby
107
- module API
108
- module V1
109
- module User
110
- module Decorator
111
- class Resource < Pragma::Decorator::Base
112
- def type
113
- :custom_type
114
- end
115
- end
116
- end
117
- end
118
- end
119
- end
120
- ```
121
-
122
- Note: `array` is already overridden with the more language-agnostic `list`.
123
-
124
- ### Associations
125
-
126
- `Pragma::Decorator::Association` allows you to define associations in your decorator (currently,
127
- only `belongs_to`/`has_one` associations are supported):
128
-
129
- ```ruby
130
- module API
131
- module V1
132
- module Invoice
133
- module Decorator
134
- class Resource < Pragma::Decorator::Base
135
- feature Pragma::Decorator::Association
136
-
137
- belongs_to :customer
138
- end
139
- end
140
- end
141
- end
142
- end
143
- ```
144
-
145
- Rendering an invoice will now create the following representation:
146
-
147
- ```json
148
- {
149
- "customer": {
150
- "id": 19
151
- }
152
- }
153
- ```
154
-
155
- Not impressed? Just wait.
156
-
157
- We also support association expansion through an interface similar to the one provided by the
158
- [Stripe API](https://stripe.com/docs/api/curl#expanding_objects). You can define which associations
159
- are expandable in the decorator:
160
-
161
- ```ruby
162
- module API
163
- module V1
164
- module Invoice
165
- module Decorator
166
- class Resource < Pragma::Decorator::Base
167
- feature Pragma::Decorator::Association
168
-
169
- belongs_to :customer, expandable: true
170
- end
171
- end
172
- end
173
- end
174
- end
175
- ```
176
-
177
- You can now pass `expand[]=customer` as a request parameter and have the `customer` property
178
- expanded into a full object!
179
-
180
- ```json
181
- {
182
- "customer": {
183
- "id": 19,
184
- "...": "..."
185
- }
186
- }
187
- ```
188
-
189
- This also works for nested associations. For instance, if the customer has a `company` association
190
- marked as expandable, you can pass `expand[]=customer&expand[]=customer.company` to get that
191
- association expanded too.
192
-
193
- In order for association expansion to work, you will have to pass the associations to expand to the
194
- representer as a user option:
195
-
196
- ```ruby
197
- decorator = API::V1::Invoice::Decorator::Resource.new(invoice)
198
- decorator.to_json(user_options: {
199
- expand: ['customer', 'customer.company', 'customer.company.contact']
200
- })
201
- ```
202
-
203
- Here's a list of options accepted when defining an association:
204
-
205
- Name | Type | Default | Meaning
206
- ---- | ---- | ------- | -------
207
- `expandable` | Boolean | `false` | Whether this association is expandable by consumers. Attempting to expand a non-expandable association will raise a `UnexpandableError`.
208
- `decorator` | Class | - | If provided, decorates the expanded object with this decorator. Otherwise, simply calls `#to_hash` on the object to get a representable hash.
209
- `render_nil` | Boolean | `false` | Whether the property should be rendered at all when it is `nil`.
210
- `exec_context` | Symbol | `:decorated` | Whether to call the getter on the decorator (`:decorator`) or the decorated object (`:decorated`).
211
-
212
- ### Timestamps
213
-
214
- [UNIX time](https://en.wikipedia.org/wiki/Unix_time) is your safest bet when rendering/parsing
215
- timestamps in your API, as it doesn't require a timezone indicator (the timezone is always UTC).
216
-
217
- You can use the `Timestamp` mixin for converting `Time` instances to UNIX times:
218
-
219
- ```ruby
220
- module API
221
- module V1
222
- module User
223
- module Decorator
224
- class Resource < Pragma::Decorator::Base
225
- feature Pragma::Decorator::Timestamp
226
-
227
- timestamp :created_at
228
- end
229
- end
230
- end
231
- end
232
- end
233
- ```
234
-
235
- This will render a user like this:
236
-
237
- ```json
238
- {
239
- "type": "user",
240
- "created_at": 1480287994
241
- }
242
- ```
243
-
244
- The `#timestamp` method supports all the options supported by `#property` (except for `:as`).
35
+ All documentation is in the [doc](https://github.com/pragmarb/pragma-decorator/tree/master/doc) folder.
245
36
 
246
37
  ## Contributing
247
38
 
@@ -0,0 +1,42 @@
1
+ # Basic usage
2
+
3
+ Creating a decorator is as simple as inheriting from `Pragma::Decorator::Base`:
4
+
5
+ ```ruby
6
+ module API
7
+ module V1
8
+ module User
9
+ module Decorator
10
+ class Resource < Pragma::Decorator::Base
11
+ property :id
12
+ property :email
13
+ property :full_name
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ ```
20
+
21
+ Just instantiate the decorator by passing it an object to decorate, then call `#to_hash` or
22
+ `#to_json`:
23
+
24
+ ```ruby
25
+ decorator = API::V1::User::Decorator::Resource.new(user)
26
+ decorator.to_json
27
+ ```
28
+
29
+ This will produce the following JSON:
30
+
31
+ ```json
32
+ {
33
+ "id": 1,
34
+ "email": "jdoe@example.com",
35
+ "full_name": "John Doe"
36
+ }
37
+ ```
38
+
39
+ Since Pragma::Decorator is built on top of [ROAR](https://github.com/apotonick/roar) (which, in
40
+ turn, is built on top of [Representable](https://github.com/apotonick/representable)), you should
41
+ consult their documentation for the basic usage of decorators; the rest of this section only covers
42
+ the features provided specifically by Pragma::Decorator.
@@ -0,0 +1,47 @@
1
+ # Object types
2
+
3
+ It is recommended that decorators expose the type of the decorated object. You can achieve this
4
+ with the `Type` mixin:
5
+
6
+ ```ruby
7
+ module API
8
+ module V1
9
+ module User
10
+ module Decorator
11
+ class Resource < Pragma::Decorator::Base
12
+ feature Pragma::Decorator::Type
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ ```
19
+
20
+ This would result in the following representation:
21
+
22
+ ```json
23
+ {
24
+ "type": "user",
25
+ "...": "...""
26
+ }
27
+ ```
28
+
29
+ You can also set a custom type name (just make sure to use it consistently!):
30
+
31
+ ```ruby
32
+ module API
33
+ module V1
34
+ module User
35
+ module Decorator
36
+ class Resource < Pragma::Decorator::Base
37
+ def type
38
+ :custom_type
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ ```
46
+
47
+ Note: `array` is already overridden with the more language-agnostic `list`.
@@ -0,0 +1,91 @@
1
+ # Associations
2
+
3
+ `Pragma::Decorator::Association` allows you to define associations in your decorator (currently,
4
+ only `belongs_to`/`has_one` associations are supported):
5
+
6
+ ```ruby
7
+ module API
8
+ module V1
9
+ module Invoice
10
+ module Decorator
11
+ class Resource < Pragma::Decorator::Base
12
+ feature Pragma::Decorator::Association
13
+
14
+ belongs_to :customer
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ ```
21
+
22
+ Rendering an invoice will now create the following representation:
23
+
24
+ ```json
25
+ {
26
+ "customer": 19
27
+ }
28
+ ```
29
+
30
+ Not impressed? Just wait.
31
+
32
+ ## Expanding associations
33
+
34
+ We also support association expansion through an interface similar to the one provided by the
35
+ [Stripe API](https://stripe.com/docs/api/curl#expanding_objects). You can define which associations
36
+ are expandable in the decorator:
37
+
38
+ ```ruby
39
+ module API
40
+ module V1
41
+ module Invoice
42
+ module Decorator
43
+ class Resource < Pragma::Decorator::Base
44
+ feature Pragma::Decorator::Association
45
+
46
+ belongs_to :customer, expandable: true
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ ```
53
+
54
+ You can now pass `expand[]=customer` as a request parameter and have the `customer` property
55
+ expanded into a full object!
56
+
57
+ ```json
58
+ {
59
+ "customer": {
60
+ "id": 19,
61
+ "...": "..."
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## Nested associations
67
+
68
+ This also works for nested associations. For instance, if the customer has a `company` association
69
+ marked as expandable, you can pass `expand[]=customer&expand[]=customer.company` to get that
70
+ association expanded too.
71
+
72
+ In order for association expansion to work, you will have to pass the associations to expand to the
73
+ representer as a user option:
74
+
75
+ ```ruby
76
+ decorator = API::V1::Invoice::Decorator::Resource.new(invoice)
77
+ decorator.to_json(user_options: {
78
+ expand: ['customer', 'customer.company', 'customer.company.contact']
79
+ })
80
+ ```
81
+
82
+ ## Accepted options
83
+
84
+ Here's a list of options accepted when defining an association:
85
+
86
+ Name | Type | Default | Meaning
87
+ ---- | ---- | ------- | -------
88
+ `expandable` | Boolean | `false` | Whether this association is expandable by consumers. Attempting to expand a non-expandable association will raise a `UnexpandableError`.
89
+ `decorator` | Class | - | If provided, decorates the expanded object with this decorator. Otherwise, simply calls `#to_hash` on the object to get a representable hash.
90
+ `render_nil` | Boolean | `false` | Whether the property should be rendered at all when it is `nil`.
91
+ `exec_context` | Symbol | `:decorated` | Whether to call the getter on the decorator (`:decorator`) or the decorated object (`:decorated`).
@@ -0,0 +1,33 @@
1
+ # Timestamps
2
+
3
+ [UNIX time](https://en.wikipedia.org/wiki/Unix_time) is your safest bet when rendering/parsing
4
+ timestamps in your API, as it doesn't require a timezone indicator (the timezone is always UTC).
5
+
6
+ You can use the `Timestamp` mixin for converting `Time` instances to UNIX times:
7
+
8
+ ```ruby
9
+ module API
10
+ module V1
11
+ module User
12
+ module Decorator
13
+ class Resource < Pragma::Decorator::Base
14
+ feature Pragma::Decorator::Timestamp
15
+
16
+ timestamp :created_at
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ ```
23
+
24
+ This will render a user like this:
25
+
26
+ ```json
27
+ {
28
+ "type": "user",
29
+ "created_at": 1480287994
30
+ }
31
+ ```
32
+
33
+ The `#timestamp` method supports all the options supported by `#property` (except for `:as`).
@@ -34,19 +34,15 @@ module Pragma
34
34
  end
35
35
  end
36
36
 
37
- # Returns the unexpanded hash for the associated object (i.e. a hash with only the +id+
38
- # property).
37
+ # Returns the unexpanded value for the associated object (i.e. its +id+ property).
39
38
  #
40
- # @return [Hash]
41
- def unexpanded_hash
39
+ # @return [String]
40
+ def unexpanded_value
42
41
  return unless associated_object
43
-
44
- {
45
- id: associated_object.id
46
- }
42
+ associated_object.id
47
43
  end
48
44
 
49
- # Returns the expanded hash for the associated object.
45
+ # Returns the expanded value for the associated object.
50
46
  #
51
47
  # If a decorator was specified for the association, first decorates the associated object,
52
48
  # then calls +#to_hash+ to render it as a hash.
@@ -61,7 +57,7 @@ module Pragma
61
57
  # @return [Hash]
62
58
  #
63
59
  # @raise [UnexpandableError] if the association is not expandable
64
- def expanded_hash(expand)
60
+ def expanded_value(expand)
65
61
  fail UnexpandableError, reflection unless reflection.expandable?
66
62
 
67
63
  return unless associated_object
@@ -91,9 +87,9 @@ module Pragma
91
87
  expand ||= []
92
88
 
93
89
  if expand.any? { |value| value.to_s == reflection.property.to_s }
94
- expanded_hash(expand)
90
+ expanded_value(expand)
95
91
  else
96
- unexpanded_hash
92
+ unexpanded_value
97
93
  end
98
94
  end
99
95
 
@@ -56,12 +56,12 @@ module Pragma
56
56
  end
57
57
 
58
58
  def validate_options
59
- unless [:decorator, :decorated].include?(options[:exec_context])
60
- fail(
61
- ArgumentError,
62
- "'#{options[:exec_context]}' is not a valid value for :exec_context."
63
- )
64
- end
59
+ return if [:decorator, :decorated].include?(options[:exec_context])
60
+
61
+ fail(
62
+ ArgumentError,
63
+ "'#{options[:exec_context]}' is not a valid value for :exec_context."
64
+ )
65
65
  end
66
66
  end
67
67
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Pragma
3
3
  module Decorator
4
- VERSION = '0.1.0'
4
+ VERSION = '1.0.0'
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pragma-decorator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Desantis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-26 00:00:00.000000000 Z
11
+ date: 2017-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: roar
@@ -139,6 +139,10 @@ files:
139
139
  - Rakefile
140
140
  - bin/console
141
141
  - bin/setup
142
+ - doc/01-basic-usage.md
143
+ - doc/02-object-types.md
144
+ - doc/03-associations.md
145
+ - doc/04-timestamps.md
142
146
  - lib/pragma/decorator.rb
143
147
  - lib/pragma/decorator/association.rb
144
148
  - lib/pragma/decorator/association/binding.rb
@@ -169,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
173
  version: '0'
170
174
  requirements: []
171
175
  rubyforge_project:
172
- rubygems_version: 2.5.2
176
+ rubygems_version: 2.6.8
173
177
  signing_key:
174
178
  specification_version: 4
175
179
  summary: Convert your API resources into JSON with minimum hassle.