tint 0.0.5 → 0.0.6

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: e0043f48824279d1625572d74b4bd9f9e7c504a4
4
- data.tar.gz: c42e86959edfd7411dba82f08736cb2b0faed36d
3
+ metadata.gz: 3bf5b7492db85d5811d4cef5eacf1ea485d0ff23
4
+ data.tar.gz: a209dcc5a5154cef5ad48ef614b2305cec5e3771
5
5
  SHA512:
6
- metadata.gz: a1d114c2f5254e27c25c41f410a9dd8d3c03b39c75d831acf6765f984a95dceadecdf8048c3f0778fbdf28585e31b67fe240ef46e40c73b3c0dff4a2038e427c
7
- data.tar.gz: d47802117dbf5598db469fa102cf67ee3392909b73cdd7f47948e91ab5af67b54cef53d5839fb9acb3c0712dbc914fc7beb8b0f804c1861666ce82144ffbc26c
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)
@@ -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)|
@@ -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
- memo[strategy.transform(key)] = value.respond_to?(:as_json) ? value.as_json : value
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
@@ -1,3 +1,3 @@
1
1
  module Tint
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
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.5
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-03-10 00:00:00.000000000 Z
11
+ date: 2017-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: draper