pragma-decorator 0.1.0 → 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 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.