tint 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +50 -27
- data/lib/tint/decorator.rb +28 -2
- data/lib/tint/json_conversion.rb +6 -5
- data/lib/tint/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bf5b7492db85d5811d4cef5eacf1ea485d0ff23
|
4
|
+
data.tar.gz: a209dcc5a5154cef5ad48ef614b2305cec5e3771
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e48ba414b74198f2fe478e9650a3b081fed327f161fc117b19dab7267d41eb66e47c9eb1dfb982e923361bcf8051ee2813d64f2308a5736532284234ab6a236
|
7
|
+
data.tar.gz: b60ef0723a9142b51576006e1e9801df62e06f6e000a3f2a31dbccb100d2e5b311fc97394ad9f1cab7aae41a9b37b86f66796e597a0d2f5f562712bacfcc4656
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Tint
|
2
2
|
|
3
|
-
Easily define object decorators for JSON APIs using simple declarative syntax
|
3
|
+
Easily define object decorators for JSON APIs using simple declarative syntax
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -22,17 +22,17 @@ You can use Tint by creating a decorator class that inherits from `Tint::Decorat
|
|
22
22
|
|
23
23
|
## Defining attributes
|
24
24
|
|
25
|
-
To include methods and attributes available on the decorated object, simply list them using `attributes`.
|
25
|
+
To include methods and attributes available on the decorated object, simply list them using `attributes`.
|
26
26
|
|
27
27
|
```ruby
|
28
28
|
# decorators/user_decorator.rb
|
29
29
|
class UserDecorator < Tint::Decorator
|
30
|
-
attributes :username, :first_name, :last_name
|
30
|
+
attributes :username, :first_name, :last_name
|
31
31
|
end
|
32
32
|
```
|
33
33
|
|
34
|
-
You can map attributes to different names on the decorator by providing a hash as the final argument
|
35
|
-
|
34
|
+
You can map attributes to different names on the decorator by providing a hash as the final argument
|
35
|
+
|
36
36
|
```ruby
|
37
37
|
# decorators/user_decorator.rb
|
38
38
|
class UserDecorator < Tint::Decorator
|
@@ -40,6 +40,29 @@ class UserDecorator < Tint::Decorator
|
|
40
40
|
end
|
41
41
|
```
|
42
42
|
|
43
|
+
## Defining attributes for *_ids
|
44
|
+
|
45
|
+
The `ids_for` method adds `*Ids` values to a JSON object and ensures the corresponding association is automatically eager loaded:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class ProductDecorator < Tint::Decorator
|
49
|
+
attributes :id, :description, :price
|
50
|
+
|
51
|
+
ids_for :sales # will add a saleIds attribute to the JSON object
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
It's possible to give the `*Ids` attribute a different name by providing the name of the association as a key-value pair:
|
56
|
+
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class ProductDecorator < Tint::Decorator
|
60
|
+
attributes :id, :description, :price
|
61
|
+
|
62
|
+
ids_for sales: :purchase_identifiers # will add a purchaseIdentifiers attribute to the JSON object
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
43
66
|
## Defining custom methods
|
44
67
|
|
45
68
|
Tint will use a decorator instance method in preference to one defined on the decorated object, so it is possible to customise how a particular attribute appears. The original definition of the attribute is available via the `object` instance variable.
|
@@ -47,9 +70,9 @@ Tint will use a decorator instance method in preference to one defined on the de
|
|
47
70
|
```ruby
|
48
71
|
class ProductDecorator < Tint::Decorator
|
49
72
|
attributes :id, :description, :price
|
50
|
-
|
73
|
+
|
51
74
|
def price
|
52
|
-
"$" + object.price
|
75
|
+
"$" + object.price
|
53
76
|
end
|
54
77
|
end
|
55
78
|
```
|
@@ -59,9 +82,9 @@ It's also possible to define methods that are not available on the decorated obj
|
|
59
82
|
```ruby
|
60
83
|
class ProductDecorator < Tint::Decorator
|
61
84
|
attributes :id, :description, :on_sale
|
62
|
-
|
85
|
+
|
63
86
|
def on_sale
|
64
|
-
SaleItems.include?(object)
|
87
|
+
SaleItems.include?(object)
|
65
88
|
end
|
66
89
|
end
|
67
90
|
```
|
@@ -79,13 +102,13 @@ end
|
|
79
102
|
# decorators/user_decorator.rb
|
80
103
|
class UserDecorator < Tint::Decorator
|
81
104
|
attributes :username
|
82
|
-
|
105
|
+
|
83
106
|
decorates_association :products
|
84
107
|
end
|
85
108
|
```
|
86
109
|
|
87
110
|
By default, `decorates_association` uses the name of the association to guess the decorator it should use. In this case it will use `ProductDecorator`, but if you wished to render with `SpecialProductDecorator`, the `with` option may be used:
|
88
|
-
|
111
|
+
|
89
112
|
```ruby
|
90
113
|
decorates_association :product, with: SpecialProductDecorator
|
91
114
|
```
|
@@ -111,26 +134,26 @@ decorates_associations :previous_address, :current_address, with: AddressDecorat
|
|
111
134
|
## Eager loading associations
|
112
135
|
|
113
136
|
When you declare a new association using `decorates_association` or `decorates_associations`, Tint automatically eager loads the associations when the decorator is rendered as JSON and automatically prevents many N+1 queries. It does this by maintaining a list `eager_loads` which is available on all decorators.
|
114
|
-
|
137
|
+
|
115
138
|
```ruby
|
116
139
|
class UserDecorator < Tint::Decorator
|
117
140
|
attributes :username
|
118
|
-
|
141
|
+
|
119
142
|
decorates_association :products
|
120
143
|
end
|
121
|
-
|
122
|
-
|
144
|
+
|
145
|
+
|
123
146
|
UserDecorator.eager_loads # [:products]
|
124
147
|
```
|
125
148
|
|
126
149
|
If you need to manually add to the list of associations which are eager loaded for any reason, you can do so using the `eager_load` method
|
127
|
-
|
150
|
+
|
128
151
|
```ruby
|
129
152
|
class UserDecorator < Tint::Decorator
|
130
153
|
attributes :username
|
131
|
-
|
154
|
+
|
132
155
|
decorates_association :products
|
133
|
-
|
156
|
+
|
134
157
|
eager_load :addresses
|
135
158
|
end
|
136
159
|
|
@@ -139,7 +162,7 @@ UserDecorator.eager_loads # [:products, :addresses]
|
|
139
162
|
|
140
163
|
## Decorating a single instance
|
141
164
|
|
142
|
-
Tint maintains the interface defined by Draper for decorating objects. To decorate a single object, use the `decorate` method.
|
165
|
+
Tint maintains the interface defined by Draper for decorating objects. To decorate a single object, use the `decorate` method.
|
143
166
|
|
144
167
|
Using the `UserDecorator` defined above:
|
145
168
|
|
@@ -150,16 +173,16 @@ class UsersController < ApplicationController
|
|
150
173
|
|
151
174
|
def show
|
152
175
|
@user = User.find(params[:id]) #<User username: "john_doe", first_name: "John", surname: "Doe">
|
153
|
-
|
176
|
+
|
154
177
|
render json: UserDecorator.decorate(@user) # { username: "john_doe", firstName: "John", lastName: "Doe" }
|
155
178
|
end
|
156
|
-
|
179
|
+
|
157
180
|
end
|
158
181
|
```
|
159
182
|
|
160
183
|
`decorate` also accepts an optional has of options. For more information about the supported options, see the [Draper documentation](https://github.com/drapergem/draper#adding-context).
|
161
|
-
|
162
|
-
|
184
|
+
|
185
|
+
|
163
186
|
## Decorating a collection
|
164
187
|
|
165
188
|
The `decorate_collection` method is used for decorating an instance of ActiveRecord::Relation (or any class that implements the same interface). It accepts all of the same options as the `decorate` method.
|
@@ -171,17 +194,17 @@ class UsersController < ApplicationController
|
|
171
194
|
|
172
195
|
def index
|
173
196
|
@users = User.all
|
174
|
-
|
197
|
+
|
175
198
|
render json: UserDecorator.decorate_collection(@users) # [ { username: "john_doe", firstName: "John", lastName: "Doe" }, ... ]
|
176
199
|
end
|
177
|
-
|
200
|
+
|
178
201
|
end
|
179
202
|
```
|
180
|
-
|
203
|
+
|
181
204
|
## Configuration
|
182
205
|
|
183
206
|
By default, Tint camelizes attribute names, however it's possible to configure Tint to use any of the following capitalization conventions:
|
184
|
-
|
207
|
+
|
185
208
|
```ruby
|
186
209
|
Tint.configuration do |config|
|
187
210
|
# attribute_naMe123 ==> attributeNaMe123 (Default)
|
data/lib/tint/decorator.rb
CHANGED
@@ -157,6 +157,34 @@ module Tint
|
|
157
157
|
true
|
158
158
|
end
|
159
159
|
|
160
|
+
def ids_for(*options)
|
161
|
+
mapped_attrs = options.extract_options!
|
162
|
+
|
163
|
+
attribute_options = options.map do |association_name|
|
164
|
+
association_method = method_name_from_association(association_name)
|
165
|
+
eager_load(association_name)
|
166
|
+
association_method
|
167
|
+
end
|
168
|
+
|
169
|
+
attribute_options.push(
|
170
|
+
mapped_attrs.inject({}) do |memo, key_and_value|
|
171
|
+
association_name, value = key_and_value
|
172
|
+
memo[value] = method_name_from_association(association_name)
|
173
|
+
|
174
|
+
eager_load(association_name)
|
175
|
+
memo
|
176
|
+
end
|
177
|
+
)
|
178
|
+
|
179
|
+
attributes(*attribute_options)
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def method_name_from_association(association)
|
185
|
+
association.to_s.singularize + '_ids'
|
186
|
+
end
|
187
|
+
|
160
188
|
def link_delegations_to_object(delegated_attrs)
|
161
189
|
@_override_methods ||= {}
|
162
190
|
|
@@ -186,8 +214,6 @@ module Tint
|
|
186
214
|
end
|
187
215
|
end
|
188
216
|
|
189
|
-
private
|
190
|
-
|
191
217
|
def expand_schema(schema)
|
192
218
|
if schema.kind_of?(Hash)
|
193
219
|
schema.inject({}) do |memo, (schema_key, schema_value)|
|
data/lib/tint/json_conversion.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
module Tint
|
2
2
|
module JsonConversion
|
3
|
-
def to_json(options={})
|
4
|
-
as_json.to_json(options)
|
5
|
-
end
|
6
|
-
|
7
3
|
def as_json(options={})
|
8
4
|
attributes_for_json
|
9
5
|
end
|
@@ -44,6 +40,10 @@ module Tint
|
|
44
40
|
end
|
45
41
|
end
|
46
42
|
|
43
|
+
def remove_js_unsafe_chars(string)
|
44
|
+
string.gsub(/[\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/, '')
|
45
|
+
end
|
46
|
+
|
47
47
|
def attributes_for_json
|
48
48
|
attribute_list = self.class._attributes
|
49
49
|
override_methods = self.class._override_methods
|
@@ -74,7 +74,8 @@ module Tint
|
|
74
74
|
end
|
75
75
|
|
76
76
|
unless value.nil?
|
77
|
-
|
77
|
+
json_value = value.respond_to?(:as_json) ? value.as_json : value
|
78
|
+
memo[strategy.transform(key)] = json_value.kind_of?(String) ? remove_js_unsafe_chars(json_value) : value
|
78
79
|
end
|
79
80
|
|
80
81
|
memo
|
data/lib/tint/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleck Greenham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: draper
|