alba 3.4.0 → 3.5.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
  SHA256:
3
- metadata.gz: d1a7b2fac43a1ae40bc0598d6f989fb7b81108d00ca929d31327113590880b2f
4
- data.tar.gz: d6bc3c22c9178eeaf8b3b7f3d3d92bc526edd18904fa736c0c25488250f89d02
3
+ metadata.gz: ad9473eff6bbd8fb5f282d2ad7c9d84ad3f104b0a5e190999bd7788fcec2d8be
4
+ data.tar.gz: f778882ced7677d043694ba257df58bea4fb09fd108804fd4c0a28b7c722cc20
5
5
  SHA512:
6
- metadata.gz: da62c8a7d30ab7c4c39032950c9e02cef238b8662f403843351116fb86e3a3010e2780a3b5efe958697fd698e7e703a130a292129f3efad4da253cc9e84570bd
7
- data.tar.gz: 94a580ab65397d4f61a8534bfd22999d86bdd9e6cca0ec83b15d03bd2fdbdedc220bbbaf091b20c34e58c7dfe5c7b21c9f046a78b25639dcecf59b71b95199c0
6
+ metadata.gz: 484f8725e3a71a7d7714f2d19e0c005c11fd995c33e59431bef48f1dac8336360fef3fdd7657f47984bded1753e366a85b4e8bd7101bd0e418c658a508788ccf
7
+ data.tar.gz: 0e7c53e58d3e9146b775b06d929b37e9860dba366114db7aca21e53628e78f946dd0ac13c7dc2788b0cc7fb10eb7211b9afc0c7ecf7c4bedd892786a07c04ea2
@@ -12,9 +12,11 @@ jobs:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  os: [ubuntu-latest, windows-latest, macos-latest]
15
- ruby: ['3.0', 3.1, 3.2, 3.3, head, jruby, truffleruby]
15
+ ruby: ['3.0', 3.1, 3.2, 3.3, 3.4, head, jruby, truffleruby]
16
16
  gemfile: [all, without_active_support, without_oj]
17
17
  exclude:
18
+ - os: windows-latest
19
+ ruby: 3.4
18
20
  - os: windows-latest
19
21
  ruby: jruby
20
22
  - os: windows-latest
data/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.5.0] 2025-01-01
10
+
11
+ ### Added
12
+
13
+ - `render_serialized_json` now works with `root_key` and `meta` [#398](https://github.com/okuramasafumi/alba/pull/398)
14
+
15
+ ### Improved
16
+
17
+ - Add transform_keys caching [#402](https://github.com/okuramasafumi/alba/pull/402)
18
+
9
19
  ## [3.4.0] 2024-12-01
10
20
 
11
21
  ### Added
data/Gemfile CHANGED
@@ -23,6 +23,16 @@ gem 'simplecov-cobertura', require: false # For test coverage
23
23
  # gem 'typeprof', require: false # For language server and typing
24
24
  gem 'yard', require: false # For documentation
25
25
 
26
+ # FIXME: There is an upstream JRuby 9.4.9.0 issue with `psych` and the latest
27
+ # version of `jar-dependencies`. The issue will be resolved with the release of
28
+ # 9.4.10.0. Then, we can remove this `jar-dependencies` dependency lock.
29
+ #
30
+ # For more information, see: https://github.com/jruby/jruby/issues/8488
31
+ #
32
+ if defined?(JRUBY_VERSION) && Gem::Version.new(JRUBY_VERSION) < Gem::Version.new('9.4.10.0')
33
+ gem 'jar-dependencies', '< 0.5' # Fix
34
+ end
35
+
26
36
  platforms :ruby do
27
37
  gem 'oj', '~> 3.11', require: false # For backend
28
38
  gem 'ruby-prof', require: false # For performance profiling
data/README.md CHANGED
@@ -686,7 +686,7 @@ Alba.serialize(something)
686
686
  # => Same as `FooResource.new(something).serialize` when `something` is an instance of `Foo`.
687
687
  ```
688
688
 
689
- Although this might be useful sometimes, it's generally recommended to define a class for Resource.
689
+ Although this might be useful sometimes, it's generally recommended to define a class for Resource. Defining a class is often more readable and more maintainable, and inline definitions cannot levarage the benefit of YJIT (it's the slowest with the benchmark YJIT enabled).
690
690
 
691
691
  #### Inline definition for multiple root keys
692
692
 
@@ -1156,7 +1156,7 @@ end
1156
1156
  class UserResource
1157
1157
  include Alba::Resource
1158
1158
 
1159
- root_key!
1159
+ root_key! # This is required to add inferred root key, otherwise it has no root key
1160
1160
 
1161
1161
  attributes :id
1162
1162
 
data/benchmark/Gemfile CHANGED
@@ -9,9 +9,11 @@ gem 'alba', path: '../'
9
9
  gem 'benchmark-ips'
10
10
  gem 'benchmark-memory'
11
11
  gem 'blueprinter'
12
+ gem 'csv'
12
13
  gem 'fast_serializer_ruby'
13
14
  gem 'jbuilder'
14
15
  gem 'jserializer'
16
+ gem 'json'
15
17
  gem 'multi_json'
16
18
  gem 'oj'
17
19
  gem 'oj_serializers'
data/benchmark/README.md CHANGED
@@ -1,6 +1,24 @@
1
1
  ## Benchmark for json serializers
2
2
 
3
- This directory contains a few different benchmark scripts. They all use inline Bundler definitions so you can run them by `ruby benchmark/collection.rb` for instance.
3
+ This directory contains a few different benchmark scripts.
4
+
5
+ ## How to run
6
+
7
+ ```
8
+ bundle install
9
+
10
+ # with `Oj.optimize_rails`
11
+ bundle exec ruby collection.rb
12
+
13
+ # without `Oj.optimize_rails`
14
+ NO_OJ_OPTIMIZE_RAILS=1 bundle exec ruby collection.rb
15
+
16
+ # with `Oj.optimize_rails` and YJIT
17
+ YJIT=1 bundle exec ruby collection.rb
18
+
19
+ # with YJIT and without `Oj.optimize_rails`
20
+ YJIT=1 NO_OJ_OPTIMIZE_RAILS=1 bundle exec ruby collection.rb
21
+ ```
4
22
 
5
23
  ## Result
6
24
 
@@ -65,7 +83,7 @@ Comparison:
65
83
  ams: 14.2 i/s - 32.28x slower
66
84
  ```
67
85
 
68
- `benchmark-ips` with `Oj.optimize_rail` and YJIT:
86
+ `benchmark-ips` with `Oj.optimize_rails` and YJIT:
69
87
 
70
88
  ```
71
89
  Comparison:
@@ -82,7 +100,7 @@ Comparison:
82
100
  ams: 20.4 i/s - 33.10x slower
83
101
  ```
84
102
 
85
- `benchmark-ips` with YJIT and without `Oj.optimize_rail`:
103
+ `benchmark-ips` with YJIT and without `Oj.optimize_rails`:
86
104
 
87
105
  ```
88
106
  Comparison:
@@ -7,6 +7,8 @@ require_relative 'prep'
7
7
 
8
8
  require "alba"
9
9
 
10
+ Alba.inflector = :active_support
11
+
10
12
  class AlbaCommentResource
11
13
  include ::Alba::Resource
12
14
  attributes :id, :body
@@ -21,6 +23,16 @@ class AlbaPostResource
21
23
  many :comments, resource: AlbaCommentResource
22
24
  end
23
25
 
26
+ class AlbaCommentWithTransformationResource < AlbaCommentResource
27
+ transform_keys :lower_camel
28
+ end
29
+
30
+ class AlbaPostWithTransformationResource < AlbaPostResource
31
+ many :comments, resource: AlbaCommentWithTransformationResource
32
+
33
+ transform_keys :lower_camel
34
+ end
35
+
24
36
  # --- ActiveModelSerializer serializers ---
25
37
 
26
38
  require "active_model_serializers"
@@ -133,7 +145,7 @@ class PostsRepresenter < Representable::Decorator
133
145
  property :id
134
146
  property :body
135
147
  property :commenter_names
136
- collection :comments
148
+ collection :comments, decorator: CommentRepresenter
137
149
  end
138
150
 
139
151
  def commenter_names
@@ -205,6 +217,7 @@ posts = Post.all.includes(:comments, :commenters)
205
217
  # --- Store the serializers in procs ---
206
218
 
207
219
  alba = Proc.new { AlbaPostResource.new(posts).serialize }
220
+ alba_with_transformation = Proc.new { AlbaPostWithTransformationResource.new(posts).serialize }
208
221
  alba_inline = Proc.new do
209
222
  Alba.serialize(posts) do
210
223
  attributes :id, :body
@@ -222,7 +235,7 @@ fast_serializer = Proc.new { FastSerializerPostResource.new(posts).to_json }
222
235
  jserializer = Proc.new { JserializerPostSerializer.new(posts, is_collection: true).to_json }
223
236
  panko = proc { Panko::ArraySerializer.new(posts, each_serializer: PankoPostSerializer).to_json }
224
237
  rails = Proc.new do
225
- ActiveSupport::JSON.encode(posts.map{ |post| post.serializable_hash(include: :comments) })
238
+ posts.to_json(include: {comments: {only: [:id, :body]}}, methods: [:commenter_names])
226
239
  end
227
240
  representable = Proc.new { PostsRepresenter.new(posts).to_json }
228
241
  simple_ams = Proc.new { SimpleAMS::Renderer::Collection.new(posts, serializer: SimpleAMSPostSerializer).to_json }
@@ -254,6 +267,7 @@ end
254
267
 
255
268
  benchmark_body = lambda do |x|
256
269
  x.report(:alba, &alba)
270
+ x.report(:alba_with_transformation, &alba_with_transformation)
257
271
  x.report(:alba_inline, &alba_inline)
258
272
  x.report(:ams, &ams)
259
273
  x.report(:blueprinter, &blueprinter)
@@ -273,3 +287,11 @@ Benchmark.ips(&benchmark_body)
273
287
 
274
288
  require 'benchmark/memory'
275
289
  Benchmark.memory(&benchmark_body)
290
+
291
+ # --- Show gem versions ---
292
+
293
+ puts "Gem versions:"
294
+ gems = %w[alba active_model_serializers blueprinter fast_serializer jserializer panko_serializer representable simple_ams turbostreamer]
295
+ Bundler.load.specs.each do |spec|
296
+ puts "#{spec.name}: #{spec.version}" if gems.include?(spec.name)
297
+ end
data/lib/alba/railtie.rb CHANGED
@@ -7,13 +7,14 @@ module Alba
7
7
  Alba.inflector = :active_support
8
8
 
9
9
  ActiveSupport.on_load(:action_controller) do
10
- define_method(:serialize) do |obj, with: nil, &block|
11
- with.nil? ? Alba.resource_with(obj, &block) : with.new(obj)
10
+ define_method(:serialize) do |obj, with: nil, root_key: nil, meta: {}, &block|
11
+ resource = with.nil? ? Alba.resource_with(obj, &block) : with.new(obj)
12
+ resource.to_json(root_key: root_key, meta: meta)
12
13
  end
13
14
 
14
- define_method(:render_serialized_json) do |obj, with: nil, &block|
15
+ define_method(:render_serialized_json) do |obj, with: nil, root_key: nil, meta: {}, &block|
15
16
  json = with.nil? ? Alba.resource_with(obj, &block) : with.new(obj)
16
- render json: json
17
+ render json: json.to_json(root_key: root_key, meta: meta)
17
18
  end
18
19
  end
19
20
  end
data/lib/alba/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Alba
4
- VERSION = '3.4.0'
4
+ VERSION = '3.5.0'
5
5
  end
data/lib/alba.rb CHANGED
@@ -117,6 +117,7 @@ module Alba
117
117
  # When it's a Class or a Module, it should have some methods, see {Alba::DefaultInflector}
118
118
  def inflector=(inflector)
119
119
  @inflector = inflector_from(inflector)
120
+ reset_transform_keys
120
121
  end
121
122
 
122
123
  # @param block [Block] resource body
@@ -144,11 +145,13 @@ module Alba
144
145
 
145
146
  # Configure Alba to symbolize keys
146
147
  def symbolize_keys!
148
+ reset_transform_keys unless @symbolize_keys
147
149
  @symbolize_keys = true
148
150
  end
149
151
 
150
152
  # Configure Alba to stringify (not symbolize) keys
151
153
  def stringify_keys!
154
+ reset_transform_keys if @symbolize_keys
152
155
  @symbolize_keys = false
153
156
  end
154
157
 
@@ -168,19 +171,22 @@ module Alba
168
171
  # @param key [String] a target key
169
172
  # @param transform_type [Symbol] a transform type, either one of `camel`, `lower_camel`, `dash` or `snake`
170
173
  # @return [String]
171
- def transform_key(key, transform_type:)
174
+ def transform_key(key, transform_type:) # rubocop:disable Metrics/MethodLength
172
175
  raise Alba::Error, 'Inflector is nil. You must set inflector before transforming keys.' unless inflector
173
176
 
174
- key = key.to_s
177
+ @_transformed_keys[transform_type][key] ||= begin
178
+ key = key.to_s
175
179
 
176
- k = case transform_type
177
- when :camel then inflector.camelize(key)
178
- when :lower_camel then inflector.camelize_lower(key)
179
- when :dash then inflector.dasherize(key)
180
- when :snake then inflector.underscore(key)
181
- else raise Alba::Error, "Unknown transform type: #{transform_type}"
182
- end
183
- regularize_key(k)
180
+ k = case transform_type
181
+ when :camel then inflector.camelize(key)
182
+ when :lower_camel then inflector.camelize_lower(key)
183
+ when :dash then inflector.dasherize(key)
184
+ when :snake then inflector.underscore(key)
185
+ else raise Alba::Error, "Unknown transform type: #{transform_type}"
186
+ end
187
+
188
+ regularize_key(k)
189
+ end
184
190
  end
185
191
 
186
192
  # Register types, used for both builtin and custom types
@@ -208,6 +214,7 @@ module Alba
208
214
  @_on_error = :raise
209
215
  @_on_nil = nil
210
216
  @types = {}
217
+ reset_transform_keys
211
218
  register_default_types
212
219
  end
213
220
 
@@ -302,6 +309,10 @@ module Alba
302
309
  inflector
303
310
  end
304
311
 
312
+ def reset_transform_keys
313
+ @_transformed_keys = Hash.new { |h, k| h[k] = {} }
314
+ end
315
+
305
316
  def register_default_types # rubocop:disable Metrics/AbcSize
306
317
  [String, :String].each do |t|
307
318
  register_type(t, check: ->(obj) { obj.is_a?(String) }, converter: lambda(&:to_s))
@@ -318,3 +329,7 @@ module Alba
318
329
 
319
330
  reset!
320
331
  end
332
+
333
+ # Monkey patch for TruffleRuby
334
+ # Delete this after 24.1.2 is released
335
+ File::SHARE_DELETE = 0 if defined?(Truffle)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alba
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.0
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OKURA Masafumi
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2024-12-01 00:00:00.000000000 Z
10
+ date: 2025-01-01 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ostruct