barley 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +332 -0
- data/Rakefile +3 -0
- data/lib/barley/cache.rb +21 -0
- data/lib/barley/configuration.rb +17 -0
- data/lib/barley/railtie.rb +4 -0
- data/lib/barley/serializable.rb +42 -0
- data/lib/barley/serializer.rb +103 -0
- data/lib/barley/version.rb +3 -0
- data/lib/barley.rb +19 -0
- data/lib/generators/serializable/USAGE +22 -0
- data/lib/generators/serializable/serializable_generator.rb +36 -0
- data/lib/generators/serializable/templates/serializer.erb +4 -0
- data/lib/generators/serializable/templates/serializer_spec.erb +7 -0
- data/lib/generators/serializable/templates/serializer_test.erb +9 -0
- data/lib/generators/serializer/USAGE +18 -0
- data/lib/generators/serializer/serializer_generator.rb +30 -0
- data/lib/generators/serializer/templates/serializer.erb +4 -0
- data/lib/generators/serializer/templates/serializer_spec.erb +7 -0
- data/lib/generators/serializer/templates/serializer_test.erb +9 -0
- data/lib/tasks/barley_tasks.rake +4 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9bc8bd44e2c9b9653aa196be4fed266d72f91cf9d9e48f9f3ed8a850d05055ec
|
4
|
+
data.tar.gz: 63417812f015521d1a266ec51fab95dbbc2a76629c095bf816ba741f30a0dc63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: de4d7276205147c55ce71acf4e4c2936772fc687c2a1353c39d5260dee8ebf13b8f32329196932bde8649f208ab5c3b6c01206a05bc35bdd4aafddf7c140e0e0
|
7
|
+
data.tar.gz: c68bd133f4ef0457f206842b6d2e2493400f142835c362e286cc10ec559b6860381375f3aba050f4ae8ad746fa5db56f2e5da9b5e66ed2ee7b656905dc4bb7f6
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright TODO: Write your name
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,332 @@
|
|
1
|
+
![Barley loqo](./img/barley.png)
|
2
|
+
|
3
|
+
Barley is a dead simple, fast, and efficient ActiveModel JSON serializer.
|
4
|
+
|
5
|
+
Cerealize your ActiveModel objects into flat JSON objects with a dead simple DSL. Our daily bread is to make your API faster.
|
6
|
+
|
7
|
+
You don't believe us? Check out the [benchmarks](#benchmarks). 😎
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
Add the `Barley::Serializable` module to your ActiveModel object.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# /app/models/user.rb
|
14
|
+
class User < ApplicationRecord
|
15
|
+
include Barley::Serializable
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
Then define your attributes and associations in a serializer class.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
# /app/serializers/user_serializer.rb
|
23
|
+
class UserSerializer < Barley::Serializer
|
24
|
+
attributes :id, :name, :email, :created_at, :updated_at
|
25
|
+
|
26
|
+
many :posts
|
27
|
+
one :group
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
The just use the `as_json` method on your model.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
user = User.find(1)
|
35
|
+
user.as_json
|
36
|
+
```
|
37
|
+
|
38
|
+
## Installation
|
39
|
+
Add this line to your application's Gemfile:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
gem "barley"
|
43
|
+
```
|
44
|
+
|
45
|
+
And then execute:
|
46
|
+
```bash
|
47
|
+
$ bundle
|
48
|
+
```
|
49
|
+
|
50
|
+
Or install it yourself as:
|
51
|
+
```bash
|
52
|
+
$ gem install barley
|
53
|
+
```
|
54
|
+
|
55
|
+
## Defining the serializer
|
56
|
+
|
57
|
+
Barley uses the model name to find the serializer class. For example, if you have a `User` model, Barley will look for a `UserSerializer` class.
|
58
|
+
|
59
|
+
You can also define the serializer class with the `serializer` macro.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# /app/models/user.rb
|
63
|
+
class User < ApplicationRecord
|
64
|
+
include Barley::Serializable
|
65
|
+
|
66
|
+
serializer UserSerializer
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
## DSL
|
71
|
+
|
72
|
+
### Attributes
|
73
|
+
You can define attributes with the `attributes` macro.
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
attributes :id, :name, :email, :created_at, :updated_at
|
77
|
+
```
|
78
|
+
|
79
|
+
You can also define attributes one by one, or a mix of both.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
attributes :id, :name, :email
|
83
|
+
attribute :created_at
|
84
|
+
attribute :updated_at
|
85
|
+
```
|
86
|
+
|
87
|
+
You can also define a custom attribute with a block. You will have a `object` variable available in the block. It is the object you are serializing.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
attribute :full_name do
|
91
|
+
"#{object.first_name} #{object.last_name}"
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
### Associations
|
96
|
+
|
97
|
+
#### One-to-one
|
98
|
+
You can define a one-to-one association with the `one` macro.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
one :group
|
102
|
+
```
|
103
|
+
|
104
|
+
You can also define a custom association with a block. You will have a `object` variable available in the block. It is the object you are serializing.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
one :group do
|
108
|
+
object.group.name
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
##### Custom serializer and caching
|
113
|
+
You can define a custom serializer for the association with the `serializer` option, and / or caching options with the `cache` option.
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
one :group, serializer: CustomGroupSerializer, cache: { expires_in: 1.hour }
|
117
|
+
```
|
118
|
+
|
119
|
+
You can of course define serializers with inner classes for simple needs.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
class UserSerializer < Barley::Serializer
|
123
|
+
attributes :id, :name, :email, :created_at, :updated_at
|
124
|
+
|
125
|
+
one :group, serializer: LocalGroupSerializer
|
126
|
+
|
127
|
+
class LocalGroupSerializer < Barley::Serializer
|
128
|
+
attributes :id, :name
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
```
|
133
|
+
end
|
134
|
+
|
135
|
+
#### One-to-many
|
136
|
+
You can define a one-to-many association with the `many` macro.
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
many :posts
|
140
|
+
```
|
141
|
+
|
142
|
+
You can also define a custom association with a block. You will have a `object` variable available in the block. It is the object you are serializing.
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
many :posts do
|
146
|
+
object.posts.map(&:title)
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
##### Custom serializer and caching
|
151
|
+
|
152
|
+
You can define a custom serializer for the association with the `serializer` option, and / or caching options with the `cache` option.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
many :posts, serializer: CustomPostSerializer, cache: { expires_in: 1.hour }
|
156
|
+
```
|
157
|
+
|
158
|
+
## Generators
|
159
|
+
You have two generators available. One to generate the serializer class:
|
160
|
+
|
161
|
+
```shell
|
162
|
+
rails generate barley:serializer User
|
163
|
+
# or
|
164
|
+
rails generate barley:serializer User --name=CustomUserSerializer
|
165
|
+
```
|
166
|
+
|
167
|
+
And one to generate both the serializer class and add the module to the model:
|
168
|
+
|
169
|
+
```shell
|
170
|
+
rails generate barley:serializable User
|
171
|
+
# or
|
172
|
+
rails generate barley:serializable User --name=CustomUserSerializer
|
173
|
+
```
|
174
|
+
|
175
|
+
## Serialization options
|
176
|
+
You can pass a hash of options to the `as_json` method.
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
user = User.find(1)
|
180
|
+
user.as_json(serializer: CustomUserSerializer, cache: { expires_in: 1.hour })
|
181
|
+
```
|
182
|
+
|
183
|
+
Beware, this gem overrides the `as_json` method on your model. Calling `as_json` with `include`, `only`, or `except` options will not work.
|
184
|
+
|
185
|
+
Why? We believe it defeats the purpose of this gem. If you want to customize the serialization of your model, you should use a serializer class.
|
186
|
+
|
187
|
+
|
188
|
+
## Caching
|
189
|
+
Barley supports caching out of the box. Just pass `cache: true` to the `serializer` macro.
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# /app/models/user.rb
|
193
|
+
# ...
|
194
|
+
serializer UserSerializer, cache: true
|
195
|
+
```
|
196
|
+
|
197
|
+
Or you can pass a hash of options to the `serializer` macro.
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
# /app/models/user.rb
|
201
|
+
# ...
|
202
|
+
serializer UserSerializer, cache: { expires_in: 1.hour }
|
203
|
+
```
|
204
|
+
|
205
|
+
### Caching options
|
206
|
+
Barley uses the MemoryStore by default. You can change the cache store with the `cache_store` option in an initializer.
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
# /config/initializers/barley.rb
|
210
|
+
Barley.configure do |config|
|
211
|
+
config.cache_store = ActiveSupport::Cache::RedisCacheStore.new
|
212
|
+
# config.cache_store = ActiveSupport::Cache::MemoryStore.new
|
213
|
+
# config.cache_store = ActiveSupport::Cache::FileStore.new
|
214
|
+
# config.cache_store = Rails.cache
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
## Breakfast mode 🤡 (coming soon)
|
219
|
+
You will soon be able to replace all occurrences of `Serializer` with `Cerealizer` in your codebase. Just for fun. And for free.
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
# /app/models/user.rb
|
223
|
+
class User < ApplicationRecord
|
224
|
+
include Barley::Cerealizable
|
225
|
+
|
226
|
+
cerealizer UserCerealizer
|
227
|
+
end
|
228
|
+
|
229
|
+
# app/cerealizers/user_cerealizer.rb
|
230
|
+
class UserCerealizer < Barley::Cerealizer
|
231
|
+
attributes :id, :name, :email, :created_at, :updated_at
|
232
|
+
|
233
|
+
many :posts
|
234
|
+
one :group
|
235
|
+
end
|
236
|
+
```
|
237
|
+
|
238
|
+
```shell
|
239
|
+
rails generate barley:cerealizer User
|
240
|
+
# etc.
|
241
|
+
```
|
242
|
+
|
243
|
+
Ah ah ah. This is so funny.
|
244
|
+
|
245
|
+
## JSON:API
|
246
|
+
No. Not yet. Maybe never. We don't know. We don't care. We don't use it. We don't like it. We don't want to. We don't have time. We don't have money. We don't have a life. We don't have a girlfriend. We don't have a boyfriend. We don't have a dog. We don't have a cat. We are generating this readme with Copilot.
|
247
|
+
|
248
|
+
## Benchmarks
|
249
|
+
This gem is blazing fast and efficient. It is 2 to 3 times faster than [ActiveModel::Serializer](https://github.com/rails-api/active_model_serializers) and twice as fast as [FastJsonapi](https://github.com/Netflix/fast_jsonapi). Memory object allocation is also much lower.
|
250
|
+
|
251
|
+
With caching enabled, it is just mind-blowing. We think. *Disclaimer: we do not serialize to the JSON:API standard, so that might be the reason why we are so fast.*
|
252
|
+
|
253
|
+
This is the result we get with the benchmark script used in the AMS repo on an Apple Silicon M1Pro processor. We will push this benchmark as soon as possible so you can see for yourself.
|
254
|
+
|
255
|
+
```shell
|
256
|
+
bundle exec ruby benchmark.rb
|
257
|
+
-- create_table("comments", {:force=>:cascade})
|
258
|
+
-> 0.0128s
|
259
|
+
-- create_table("posts", {:force=>:cascade})
|
260
|
+
-> 0.0002s
|
261
|
+
-- create_table("users", {:force=>:cascade})
|
262
|
+
-> 0.0002s
|
263
|
+
Warming up --------------------------------------
|
264
|
+
ams 3.000 i/100ms
|
265
|
+
jsonapi-rb 9.000 i/100ms
|
266
|
+
barley 9.000 i/100ms
|
267
|
+
barley-cache 460.000 i/100ms
|
268
|
+
ams eager 8.000 i/100ms
|
269
|
+
jsonapi-rb eager 33.000 i/100ms
|
270
|
+
barley eager 37.000 i/100ms
|
271
|
+
barley-cache eager 70.000 i/100ms
|
272
|
+
Calculating -------------------------------------
|
273
|
+
ams 67.770 (± 1.9%) i/s - 657.000 in 10.042270s
|
274
|
+
jsonapi-rb 157.239 (± 2.3%) i/s - 1.521k in 10.010257s
|
275
|
+
barley 96.909 (± 2.4%) i/s - 945.000 in 10.036316s
|
276
|
+
barley-cache 4.589k (± 2.8%) i/s - 44.620k in 10.010004s
|
277
|
+
ams eager 68.237 (± 6.2%) i/s - 592.000 in 10.087602s
|
278
|
+
jsonapi-rb eager 289.733 (± 3.7%) i/s - 2.805k in 10.033912s
|
279
|
+
barley eager 406.732 (± 3.2%) i/s - 3.922k in 10.020076s
|
280
|
+
barley-cache eager 639.935 (± 2.4%) i/s - 6.300k in 10.053710s
|
281
|
+
with 95.0% confidence
|
282
|
+
|
283
|
+
Comparison:
|
284
|
+
barley-cache : 4589.3 i/s
|
285
|
+
barley-cache eager: 639.9 i/s - 7.17x (± 0.27) slower
|
286
|
+
barley eager: 406.7 i/s - 11.29x (± 0.49) slower
|
287
|
+
jsonapi-rb eager: 289.7 i/s - 15.83x (± 0.74) slower
|
288
|
+
jsonapi-rb : 157.2 i/s - 29.17x (± 1.08) slower
|
289
|
+
barley : 96.9 i/s - 47.37x (± 1.75) slower
|
290
|
+
ams eager: 68.2 i/s - 67.25x (± 4.69) slower
|
291
|
+
ams : 67.8 i/s - 67.72x (± 2.31) slower
|
292
|
+
with 95.0% confidence
|
293
|
+
|
294
|
+
Calculating -------------------------------------
|
295
|
+
ams 1.300M memsize ( 246.338k retained)
|
296
|
+
16.838k objects ( 2.492k retained)
|
297
|
+
50.000 strings ( 50.000 retained)
|
298
|
+
jsonapi-rb 926.082k memsize ( 197.338k retained)
|
299
|
+
9.565k objects ( 1.776k retained)
|
300
|
+
50.000 strings ( 50.000 retained)
|
301
|
+
barley 1.102M memsize ( 177.490k retained)
|
302
|
+
12.930k objects ( 1.876k retained)
|
303
|
+
50.000 strings ( 35.000 retained)
|
304
|
+
barley-cache 46.090k memsize ( 1.308k retained)
|
305
|
+
502.000 objects ( 17.000 retained)
|
306
|
+
42.000 strings ( 6.000 retained)
|
307
|
+
ams eager 1.068M memsize ( 233.994k retained)
|
308
|
+
13.723k objects ( 2.308k retained)
|
309
|
+
50.000 strings ( 50.000 retained)
|
310
|
+
jsonapi-rb eager 694.430k memsize ( 194.826k retained)
|
311
|
+
6.450k objects ( 1.651k retained)
|
312
|
+
50.000 strings ( 50.000 retained)
|
313
|
+
barley eager 354.326k memsize ( 124.282k retained)
|
314
|
+
3.694k objects ( 1.208k retained)
|
315
|
+
50.000 strings ( 32.000 retained)
|
316
|
+
barley-cache eager 216.790k memsize ( 107.228k retained)
|
317
|
+
2.376k objects ( 956.000 retained)
|
318
|
+
50.000 strings ( 33.000 retained)
|
319
|
+
|
320
|
+
Comparison:
|
321
|
+
barley-cache : 46090 allocated
|
322
|
+
barley-cache eager: 216790 allocated - 4.70x more
|
323
|
+
barley eager: 354326 allocated - 7.69x more
|
324
|
+
jsonapi-rb eager: 694430 allocated - 15.07x more
|
325
|
+
jsonapi-rb : 926082 allocated - 20.09x more
|
326
|
+
ams eager: 1068038 allocated - 23.17x more
|
327
|
+
barley : 1102354 allocated - 23.92x more
|
328
|
+
ams : 1299674 allocated - 28.20x more
|
329
|
+
```
|
330
|
+
|
331
|
+
## License
|
332
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/lib/barley/cache.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Barley
|
4
|
+
class Cache
|
5
|
+
class << self
|
6
|
+
delegate :fetch, :delete, to: :new
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@cache_store = Barley.config.cache_store
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(key, options = {}, &block)
|
14
|
+
@cache_store.fetch(key, options, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete(key)
|
18
|
+
@cache_store.delete(key)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Barley
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :cache_store
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@cache_store = default_cache_store
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def default_cache_store
|
14
|
+
ActiveSupport::Cache::MemoryStore.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Barley
|
4
|
+
# Makes a Model serializable
|
5
|
+
#
|
6
|
+
# * Allows setting a default model Serializer
|
7
|
+
# @example
|
8
|
+
# class Item < ApplicationRecord
|
9
|
+
# include Barley::Serializable
|
10
|
+
#
|
11
|
+
# # optionally define the default serializer, otherwise defaults to ItemSerializer
|
12
|
+
# serializer MyCustomItemSerializer, cache: true
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# #> Item.as_json
|
16
|
+
module Serializable
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
class_methods do
|
20
|
+
# @example without cache
|
21
|
+
# serializer ItemSerializer
|
22
|
+
# @example with cache
|
23
|
+
# serializer ItemSerializer, cache: true
|
24
|
+
# @example with cache and expires_in
|
25
|
+
# serializer ItemSerializer, cache: {expires_in: 1.hour}
|
26
|
+
def serializer(klass, cache: false)
|
27
|
+
define_method(:serializer) do
|
28
|
+
klass.new(self, cache: cache)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
included do
|
34
|
+
serializer "#{self}Serializer".constantize
|
35
|
+
|
36
|
+
def as_json(serializer: nil, cache: false)
|
37
|
+
serializer ||= self.serializer.class
|
38
|
+
serializer.new(self, cache: cache).as_json
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Barley
|
4
|
+
class Serializer
|
5
|
+
attr_accessor :object
|
6
|
+
|
7
|
+
# @example with cache
|
8
|
+
# Barley::Serializer.new(object, cache: true)
|
9
|
+
# @example with cache and expires_in
|
10
|
+
# Barley::Serializer.new(object, cache: {expires_in: 1.hour})
|
11
|
+
def initialize(object, cache: false)
|
12
|
+
@object = object
|
13
|
+
@cache, @expires_in = if cache.is_a?(Hash)
|
14
|
+
[true, cache[:expires_in]]
|
15
|
+
else
|
16
|
+
[cache, nil]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.attributes(*keys)
|
21
|
+
keys.each do |key|
|
22
|
+
define_method(key) do
|
23
|
+
object.send(key)
|
24
|
+
end
|
25
|
+
set_class_iv(:@defined_attributes, key)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.attribute(key, &block)
|
30
|
+
if block
|
31
|
+
define_method(key) do
|
32
|
+
instance_eval(&block)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
define_method(key) do
|
36
|
+
object.send(key)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
set_class_iv(:@defined_attributes, key)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.set_class_iv(iv, key)
|
43
|
+
instance_variable_defined?(iv) ? instance_variable_get(iv) << key : instance_variable_set(iv, [key])
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.one(key, serializer: nil, cache: false)
|
47
|
+
define_method(key) do
|
48
|
+
element = object.send(key)
|
49
|
+
return {} if element.nil?
|
50
|
+
|
51
|
+
el_serializer = serializer || element.serializer.class
|
52
|
+
el_serializer.new(element, cache: cache).as_json
|
53
|
+
end
|
54
|
+
set_class_iv(:@defined_attributes, key)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.many(key, serializer: nil, cache: false)
|
58
|
+
define_method(key) do
|
59
|
+
elements = object.send(key)
|
60
|
+
return [] if elements.empty?
|
61
|
+
|
62
|
+
el_serializer = serializer || elements.first.serializer.class
|
63
|
+
elements.map { |element| el_serializer.new(element, cache: cache).as_json }.reject(&:blank?)
|
64
|
+
end
|
65
|
+
set_class_iv(:@defined_attributes, key)
|
66
|
+
end
|
67
|
+
|
68
|
+
def as_json
|
69
|
+
if @cache
|
70
|
+
cache_key = cache_base_key
|
71
|
+
Barley::Cache.fetch(cache_key, expires_in: @expires_in) do
|
72
|
+
_as_json
|
73
|
+
end
|
74
|
+
else
|
75
|
+
_as_json
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def clear_cache(key: cache_base_key)
|
80
|
+
Barley::Cache.delete(key)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def cache_base_key
|
86
|
+
"#{self.class.name.underscore}/#{object.id}/#{object.updated_at.to_i}/as_json/"
|
87
|
+
end
|
88
|
+
|
89
|
+
def defined_attributes
|
90
|
+
self.class.instance_variable_get(:@defined_attributes)
|
91
|
+
end
|
92
|
+
|
93
|
+
def _as_json
|
94
|
+
hash = {}
|
95
|
+
|
96
|
+
defined_attributes.each do |key|
|
97
|
+
hash[key] = send(key)
|
98
|
+
end
|
99
|
+
|
100
|
+
hash
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/barley.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "barley/version"
|
2
|
+
require "barley/railtie"
|
3
|
+
require "barley/configuration"
|
4
|
+
|
5
|
+
module Barley
|
6
|
+
mattr_accessor :config
|
7
|
+
|
8
|
+
self.config = Configuration.new
|
9
|
+
|
10
|
+
def self.configure
|
11
|
+
self.config ||= Configuration.new
|
12
|
+
yield(config)
|
13
|
+
end
|
14
|
+
|
15
|
+
autoload :Cache, "barley/cache"
|
16
|
+
autoload :Error, "barley/error"
|
17
|
+
autoload :Serializable, "barley/serializable"
|
18
|
+
autoload :Serializer, "barley/serializer"
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Description:
|
2
|
+
Explain the generator
|
3
|
+
|
4
|
+
Example:
|
5
|
+
bin/rails generate serializable Thing
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
app/serializers/thing_serializer.rb
|
9
|
+
spec/serializers/thing_serializer_spec.rb # if rspec is installed
|
10
|
+
test/serializers/thing_serializer_test.rb # if minitest is installed
|
11
|
+
And update:
|
12
|
+
app/models/thing.rb
|
13
|
+
|
14
|
+
Example:
|
15
|
+
bin/rails generate serializable Thing --name=CustomThingSerializer
|
16
|
+
|
17
|
+
This will create:
|
18
|
+
app/serializers/custom_thing_serializer.rb
|
19
|
+
spec/serializers/custom_thing_serializer_spec.rb # if rspec is installed
|
20
|
+
test/serializers/custom_thing_serializer_test.rb # if minitest is installed
|
21
|
+
And update:
|
22
|
+
app/models/thing.rb
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SerializableGenerator < Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
class_option :name, type: :string, desc: "Custom serializer name"
|
7
|
+
|
8
|
+
def modify_model_file
|
9
|
+
inject_into_class File.join("app/models", class_path, "#{class_name.underscore}.rb"), class_name do
|
10
|
+
" include Barley::Serializable\n"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_serializer_file
|
15
|
+
@serializer_name = options[:name] || "#{class_name}Serializer"
|
16
|
+
file_name = @serializer_name.underscore
|
17
|
+
template "serializer.erb", File.join("app/serializers", class_path, "#{file_name}.rb")
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_test_file
|
21
|
+
@serializer_name = options[:name] || "#{class_name}Serializer"
|
22
|
+
(Bundler.load.specs.find { |s| s.name == "rspec-rails" }) ? create_rspec_test_file : create_minitest_test_file
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_rspec_test_file
|
28
|
+
file_name = @serializer_name.underscore
|
29
|
+
template "serializer_spec.erb", File.join("spec/serializers", class_path, "#{file_name}_spec.rb")
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_minitest_test_file
|
33
|
+
file_name = @serializer_name.underscore
|
34
|
+
template "serializer_test.erb", File.join("test/serializers", class_path, "#{file_name}_test.rb")
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Description:
|
2
|
+
Explain the generator
|
3
|
+
|
4
|
+
Example:
|
5
|
+
bin/rails generate serializer Thing
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
app/serializers/thing_serializer.rb
|
9
|
+
spec/serializers/thing_serializer_spec.rb # if rspec is installed
|
10
|
+
test/serializers/thing_serializer_test.rb # if minitest is installed
|
11
|
+
|
12
|
+
Example:
|
13
|
+
bin/rails generate serializer Thing --name=CustomThingSerializer
|
14
|
+
|
15
|
+
This will create:
|
16
|
+
app/serializers/custom_thing_serializer.rb
|
17
|
+
spec/serializers/custom_thing_serializer_spec.rb # if rspec is installed
|
18
|
+
test/serializers/custom_thing_serializer_test.rb # if minitest is installed
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class SerializerGenerator < Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
class_option :name, type: :string, desc: "Custom serializer name"
|
7
|
+
|
8
|
+
def create_serializer_file
|
9
|
+
@serializer_name = options[:name] || "#{class_name}Serializer"
|
10
|
+
file_name = @serializer_name.underscore
|
11
|
+
template "serializer.erb", File.join("app/serializers", class_path, "#{file_name}.rb")
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_test_file
|
15
|
+
@serializer_name = options[:name] || "#{class_name}Serializer"
|
16
|
+
(Bundler.load.specs.find { |s| s.name == "rspec-rails" }) ? create_rspec_test_file : create_minitest_test_file
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def create_rspec_test_file
|
22
|
+
file_name = @serializer_name.underscore
|
23
|
+
template "serializer_spec.erb", File.join("spec/serializers", class_path, "#{file_name}_spec.rb")
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_minitest_test_file
|
27
|
+
file_name = @serializer_name.underscore
|
28
|
+
template "serializer_test.erb", File.join("test/serializers", class_path, "#{file_name}_test.rb")
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: barley
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cedric Delalande
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-10-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 6.1.0
|
27
|
+
description: Cerealize your ActiveModel objects into flat JSON objects with a dead
|
28
|
+
simple DSL. Our daily bread is to make your API faster.
|
29
|
+
email:
|
30
|
+
- weengs@moskitohero.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- MIT-LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- lib/barley.rb
|
39
|
+
- lib/barley/cache.rb
|
40
|
+
- lib/barley/configuration.rb
|
41
|
+
- lib/barley/railtie.rb
|
42
|
+
- lib/barley/serializable.rb
|
43
|
+
- lib/barley/serializer.rb
|
44
|
+
- lib/barley/version.rb
|
45
|
+
- lib/generators/serializable/USAGE
|
46
|
+
- lib/generators/serializable/serializable_generator.rb
|
47
|
+
- lib/generators/serializable/templates/serializer.erb
|
48
|
+
- lib/generators/serializable/templates/serializer_spec.erb
|
49
|
+
- lib/generators/serializable/templates/serializer_test.erb
|
50
|
+
- lib/generators/serializer/USAGE
|
51
|
+
- lib/generators/serializer/serializer_generator.rb
|
52
|
+
- lib/generators/serializer/templates/serializer.erb
|
53
|
+
- lib/generators/serializer/templates/serializer_spec.erb
|
54
|
+
- lib/generators/serializer/templates/serializer_test.erb
|
55
|
+
- lib/tasks/barley_tasks.rake
|
56
|
+
homepage: https://github.com/moskitohero/barley
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata:
|
60
|
+
homepage_uri: https://github.com/moskitohero/barley
|
61
|
+
source_code_uri: https://github.com/moskitohero/barley
|
62
|
+
changelog_uri: https://github.com/moskitohero/barley/CHANGELOG.md
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubygems_version: 3.2.33
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Barley is a dead simple, fast, and efficient ActiveModel JSON serializer.
|
82
|
+
test_files: []
|