barley 0.1.0 → 0.3.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
  SHA256:
3
- metadata.gz: 9bc8bd44e2c9b9653aa196be4fed266d72f91cf9d9e48f9f3ed8a850d05055ec
4
- data.tar.gz: 63417812f015521d1a266ec51fab95dbbc2a76629c095bf816ba741f30a0dc63
3
+ metadata.gz: be82895a01fc1f0be3170a9a105b7fdf20b7e98d31a77c74c5d9f67068814dec
4
+ data.tar.gz: 276dcc80814079aed898b1e4d1d9e5b6bf3bc4b8b6b86f2b5cff701961d2b877
5
5
  SHA512:
6
- metadata.gz: de4d7276205147c55ce71acf4e4c2936772fc687c2a1353c39d5260dee8ebf13b8f32329196932bde8649f208ab5c3b6c01206a05bc35bdd4aafddf7c140e0e0
7
- data.tar.gz: c68bd133f4ef0457f206842b6d2e2493400f142835c362e286cc10ec559b6860381375f3aba050f4ae8ad746fa5db56f2e5da9b5e66ed2ee7b656905dc4bb7f6
6
+ metadata.gz: 9f3482dc0562669991a64403c9c5cee510d61cc5ec79affa3715eb203ac1a48f1f15c676778d380eccbfe6efc57281eae6c179ab4378a62d35c31b0fd65529ea
7
+ data.tar.gz: b9d2a98edf8704acf8b8466042b924b771384e1756fd06f9d23939f9bd0fb4368a4934303057edd0a53d0c8f487dc93c10649e39fe17b3031189f383a668ec54
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Barley is a dead simple, fast, and efficient ActiveModel JSON serializer.
4
4
 
5
- Cerealize your ActiveModel objects into flat JSON objects with a dead simple DSL. Our daily bread is to make your API faster.
5
+ Cerealize your ActiveModel objects into flat hashes with a dead simple, yet versatile DSL, and caching baked in. Our daily bread is to make your API faster.
6
6
 
7
7
  You don't believe us? Check out the [benchmarks](#benchmarks). 😎
8
8
 
@@ -21,10 +21,19 @@ Then define your attributes and associations in a serializer class.
21
21
  ```ruby
22
22
  # /app/serializers/user_serializer.rb
23
23
  class UserSerializer < Barley::Serializer
24
- attributes :id, :name, :email, :created_at, :updated_at
25
-
26
- many :posts
27
- one :group
24
+ attributes :id, :name,
25
+ attribute :email # single attribute
26
+
27
+ many :posts # relations
28
+ one :group, serializer: CustomGroupSerializer # custom serializer
29
+ many :related_users, key: :friends, cache: true # custom key, and caching
30
+ one :profile, cache: { expires_in: 1.day } do # cache definition, and block (on associations) for nested, on-the-fly serializer
31
+ attributes :avatar, :social_url
32
+ attribute :badges do
33
+ object.badges.map(&:display_name) # use object in a block to return custom code
34
+ end
35
+ end
36
+
28
37
  end
29
38
  ```
30
39
 
@@ -92,6 +101,12 @@ You can also define a custom attribute with a block. You will have a `object` va
92
101
  end
93
102
  ```
94
103
 
104
+ You can also set a custom key name for the attribute with the `key_name` option.
105
+
106
+ ```ruby
107
+ attribute :updated_at, key: :last_change
108
+ ```
109
+
95
110
  ### Associations
96
111
 
97
112
  #### One-to-one
@@ -101,14 +116,6 @@ You can define a one-to-one association with the `one` macro.
101
116
  one :group
102
117
  ```
103
118
 
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
119
  ##### Custom serializer and caching
113
120
  You can define a custom serializer for the association with the `serializer` option, and / or caching options with the `cache` option.
114
121
 
@@ -128,9 +135,15 @@ class UserSerializer < Barley::Serializer
128
135
  attributes :id, :name
129
136
  end
130
137
  end
138
+ ```
139
+
140
+ ##### Key name
131
141
 
142
+ You can also pass a key name for the association with the `key_name` option.
143
+
144
+ ```ruby
145
+ one :group, key_name: :team
132
146
  ```
133
- end
134
147
 
135
148
  #### One-to-many
136
149
  You can define a one-to-many association with the `many` macro.
@@ -139,20 +152,38 @@ You can define a one-to-many association with the `many` macro.
139
152
  many :posts
140
153
  ```
141
154
 
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.
155
+ ##### Custom serializer and caching
156
+
157
+ You can define a custom serializer for the association with the `serializer` option, and / or caching options with the `cache` option.
143
158
 
144
159
  ```ruby
145
- many :posts do
146
- object.posts.map(&:title)
147
- end
160
+ many :posts, serializer: CustomPostSerializer, cache: { expires_in: 1.hour }
148
161
  ```
149
162
 
150
- ##### Custom serializer and caching
163
+ ##### Key name
164
+ You can also pass a key name for the association with the `key_name` option.
151
165
 
152
- You can define a custom serializer for the association with the `serializer` option, and / or caching options with the `cache` option.
166
+ ```ruby
167
+ many :posts, key_name: :articles
168
+ ```
169
+
170
+ ### Associations with blocks
171
+ Feel like using a block to define your associations? You can do that too.
153
172
 
154
173
  ```ruby
155
- many :posts, serializer: CustomPostSerializer, cache: { expires_in: 1.hour }
174
+ one :group do
175
+ attributes :id, :name
176
+ end
177
+ ```
178
+
179
+ ```ruby
180
+ many :posts do
181
+ attributes :id, :title, :body
182
+
183
+ one :author do
184
+ attributes :name, :email
185
+ end
186
+ end
156
187
  ```
157
188
 
158
189
  ## Generators
@@ -209,9 +240,6 @@ Barley uses the MemoryStore by default. You can change the cache store with the
209
240
  # /config/initializers/barley.rb
210
241
  Barley.configure do |config|
211
242
  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
243
  end
216
244
  ```
217
245
 
@@ -242,15 +270,17 @@ rails generate barley:cerealizer User
242
270
 
243
271
  Ah ah ah. This is so funny.
244
272
 
273
+ *Note: we are thinking about adding a `Surrealizer` class for the most advanced users. Stay tuned.*
274
+
245
275
  ## 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.
276
+ Barley does not serialize to the JSON:API standard. We prefer to keep it simple and fast.
247
277
 
248
278
  ## Benchmarks
249
279
  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
280
 
251
281
  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
282
 
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.
283
+ This is the result we get with the benchmark script used in the AMS repo on an Apple Silicon M1Pro processor. [Check it out for yourself here](https://github.com/MoskitoHero/active_model_serializers/tree/benchmarks).
254
284
 
255
285
  ```shell
256
286
  bundle exec ruby benchmark.rb
@@ -330,3 +360,8 @@ ams : 1299674 allocated - 28.20x more
330
360
 
331
361
  ## License
332
362
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
363
+
364
+ ## Credits
365
+ Barley is brought to you by the developer team from [StockPro](https://www.stock-pro.fr/).
366
+
367
+ [![Barley is brought to you by StockPro](img/stockpro.png)](https://www.stock-pro.fr/)
@@ -33,9 +33,9 @@ module Barley
33
33
  included do
34
34
  serializer "#{self}Serializer".constantize
35
35
 
36
- def as_json(serializer: nil, cache: false)
36
+ def as_json(serializer: nil, cache: false, root: false)
37
37
  serializer ||= self.serializer.class
38
- serializer.new(self, cache: cache).as_json
38
+ serializer.new(self, cache: cache, root: root).serializable_hash
39
39
  end
40
40
  end
41
41
  end
@@ -4,75 +4,90 @@ module Barley
4
4
  class Serializer
5
5
  attr_accessor :object
6
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]
7
+ class << self
8
+ def attributes(*keys)
9
+ keys.each do |key|
10
+ define_method(key) do
11
+ object.send(key)
12
+ end
13
+ set_class_iv(:@defined_attributes, key)
14
+ end
17
15
  end
18
- end
19
16
 
20
- def self.attributes(*keys)
21
- keys.each do |key|
22
- define_method(key) do
23
- object.send(key)
17
+ def attribute(key, key_name: nil, &block)
18
+ key_name ||= key
19
+ if block
20
+ define_method(key_name) do
21
+ instance_eval(&block)
22
+ end
23
+ else
24
+ define_method(key_name) do
25
+ object.send(key)
26
+ end
24
27
  end
25
- set_class_iv(:@defined_attributes, key)
28
+ set_class_iv(:@defined_attributes, key_name)
26
29
  end
27
- end
28
30
 
29
- def self.attribute(key, &block)
30
- if block
31
- define_method(key) do
32
- instance_eval(&block)
31
+ def one(key, key_name: nil, serializer: nil, cache: false, &block)
32
+ key_name ||= key
33
+ if block
34
+ serializer = Class.new(Barley::Serializer) do
35
+ instance_eval(&block)
36
+ end
33
37
  end
34
- else
35
- define_method(key) do
36
- object.send(key)
38
+ define_method(key_name) do
39
+ element = object.send(key)
40
+ return {} if element.nil?
41
+
42
+ el_serializer = serializer || element.serializer.class
43
+ el_serializer.new(element, cache: cache).serializable_hash
37
44
  end
45
+ set_class_iv(:@defined_attributes, key_name)
38
46
  end
39
- set_class_iv(:@defined_attributes, key)
40
- end
41
47
 
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
48
+ def many(key, key_name: nil, serializer: nil, cache: false, &block)
49
+ key_name ||= key
50
+ if block
51
+ serializer = Class.new(Barley::Serializer) do
52
+ instance_eval(&block)
53
+ end
54
+ end
55
+ define_method(key_name) do
56
+ elements = object.send(key)
57
+ return [] if elements.empty?
45
58
 
46
- def self.one(key, serializer: nil, cache: false)
47
- define_method(key) do
48
- element = object.send(key)
49
- return {} if element.nil?
59
+ el_serializer = serializer || elements.first.serializer.class
60
+ elements.map { |element| el_serializer.new(element, cache: cache).serializable_hash }.reject(&:blank?)
61
+ end
62
+ set_class_iv(:@defined_attributes, key_name)
63
+ end
50
64
 
51
- el_serializer = serializer || element.serializer.class
52
- el_serializer.new(element, cache: cache).as_json
65
+ def set_class_iv(iv, key)
66
+ instance_variable_defined?(iv) ? instance_variable_get(iv) << key : instance_variable_set(iv, [key])
53
67
  end
54
- set_class_iv(:@defined_attributes, key)
55
68
  end
56
69
 
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?)
70
+ # @example with cache
71
+ # Barley::Serializer.new(object, cache: true)
72
+ # @example with cache and expires_in
73
+ # Barley::Serializer.new(object, cache: {expires_in: 1.hour})
74
+ def initialize(object, cache: false, root: false)
75
+ @object = object
76
+ @root = root
77
+ @cache, @expires_in = if cache.is_a?(Hash)
78
+ [true, cache[:expires_in]]
79
+ else
80
+ [cache, nil]
64
81
  end
65
- set_class_iv(:@defined_attributes, key)
66
82
  end
67
83
 
68
- def as_json
84
+ def serializable_hash
69
85
  if @cache
70
- cache_key = cache_base_key
71
- Barley::Cache.fetch(cache_key, expires_in: @expires_in) do
72
- _as_json
86
+ Barley::Cache.fetch(cache_base_key, expires_in: @expires_in) do
87
+ _serializable_hash
73
88
  end
74
89
  else
75
- _as_json
90
+ _serializable_hash
76
91
  end
77
92
  end
78
93
 
@@ -83,21 +98,29 @@ module Barley
83
98
  private
84
99
 
85
100
  def cache_base_key
86
- "#{self.class.name.underscore}/#{object.id}/#{object.updated_at.to_i}/as_json/"
101
+ if object.updated_at.present?
102
+ "#{object.class.name&.underscore}/#{object.id}/#{object.updated_at&.to_i}/barley_cache/"
103
+ else
104
+ "#{object.class.name&.underscore}/#{object.id}/barley_cache/"
105
+ end
87
106
  end
88
107
 
89
108
  def defined_attributes
90
109
  self.class.instance_variable_get(:@defined_attributes)
91
110
  end
92
111
 
93
- def _as_json
112
+ def _serializable_hash
94
113
  hash = {}
95
114
 
96
115
  defined_attributes.each do |key|
97
116
  hash[key] = send(key)
98
117
  end
99
118
 
100
- hash
119
+ @root ? {root_key => hash} : hash
120
+ end
121
+
122
+ def root_key
123
+ object.class.name.underscore.to_sym
101
124
  end
102
125
  end
103
126
  end
@@ -1,3 +1,3 @@
1
1
  module Barley
2
- VERSION = "0.1.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: barley
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cedric Delalande
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-10 00:00:00.000000000 Z
11
+ date: 2023-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails