From 5b80ffb8c3a070006ef504569cf5f3e9daf4bbad Mon Sep 17 00:00:00 2001 From: OKURA Masafumi Date: Tue, 19 Mar 2024 23:53:53 +0900 Subject: [PATCH 1/2] [Feat] Add the ability to change key for metadata --- README.md | 59 ++++++++++++++++++++++++++ lib/alba/resource.rb | 19 ++++++--- test/usecases/meta_test.rb | 85 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3bd4f86..6cd4028 100644 --- a/README.md +++ b/README.md @@ -1233,6 +1233,65 @@ UserResource.new([user]).serialize UserResource.new([user]).serialize(meta: {foo: :bar}) # => '{"users":[{"id":1,"name":"Masafumi OKURA"}],"meta":{"size":1,"foo":"bar"}}' +``` + +You can change the key for metadata. If you change the key, it also affects the key when you pass `meta` option. + +```ruby +# You can change meta key +class UserResourceWithDifferentMetaKey + include Alba::Resource + + root_key :user, :users + + attributes :id, :name + + meta :my_meta do + {foo: :bar} + end +end + +UserResourceWithDifferentMetaKey.new([user]).serialize +# => '{"users":[{"id":1,"name":"Masafumi OKURA"}],"my_meta":{"foo":"bar"}}' + +UserResourceWithDifferentMetaKey.new([user]).serialize(meta: {extra: 42}) +# => '{"users":[{"id":1,"name":"Masafumi OKURA"}],"meta":{"size":1,"extra":42}}' + +class UserResourceChangingMetaKeyOnly + include Alba::Resource + + root_key :user, :users + + attributes :id, :name + + meta :my_meta +end + +UserResourceChangingMetaKeyOnly.new([user]).serialize +# => '{"users":[{"id":1,"name":"Masafumi OKURA"}]}' + +UserResourceChangingMetaKeyOnly.new([user]).serialize(meta: {extra: 42}) +# => '{"users":[{"id":1,"name":"Masafumi OKURA"}],"my_meta":{"extra":42}}' +``` + +It's also possible to remove the key for metadata, resulting a flat structure. + +```ruby +class UserResourceRemovingMetaKey + include Alba::Resource + + root_key :user, :users + + attributes :id, :name + + meta nil +end + +UserResourceRemovingMetaKey.new([user]).serialize +# => '{"users":[{"id":1,"name":"Masafumi OKURA"}]}' + +UserResourceRemovingMetaKey.new([user]).serialize(meta: {extra: 42}) +# => '{"users":[{"id":1,"name":"Masafumi OKURA"}],"extra":42}' # You can set metadata with `meta` option alone diff --git a/lib/alba/resource.rb b/lib/alba/resource.rb index 19d6bed..c7c91ee 100644 --- a/lib/alba/resource.rb +++ b/lib/alba/resource.rb @@ -111,13 +111,22 @@ def serialize_with(hash) end def hash_with_metadata(hash, meta) - return hash if meta.empty? && @_meta.nil? + return hash if meta.empty? && @_meta&.last.nil? - metadata = @_meta ? instance_eval(&@_meta).merge(meta) : meta - hash[:meta] = metadata + key, block = @_meta || :meta + + if key + hash[key] = _metadata(block, meta) + else + _metadata(block, meta).each { |k, v| hash[k] = v } + end hash end + def _metadata(block, meta) + block ? instance_eval(&block).merge(meta) : meta + end + def serializable_hash_for_collection if @_collection_key @object.to_h do |item| @@ -446,8 +455,8 @@ def root_key! end # Set metadata - def meta(&block) - @_meta = block + def meta(key = :meta, &block) + @_meta = [key, block] end # Set layout diff --git a/test/usecases/meta_test.rb b/test/usecases/meta_test.rb index 3bedc1c..d802de4 100644 --- a/test/usecases/meta_test.rb +++ b/test/usecases/meta_test.rb @@ -93,4 +93,89 @@ def test_it_includes_meta_with_given_meta_option_without_meta_dsl UserResourceWithoutMeta.new([@user]).serialize(meta: {class: 'MetaTest'}) ) end + + class UserResource2 + include Alba::Resource + + root_key :user, :users + + attributes :id, :name + + meta :my_meta do + if object.is_a?(Enumerable) + {size: object.size} + else + {foo: :bar} + end + end + end + + def test_changing_meta_key + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}],"my_meta":{"size":1}}', + UserResource2.new([@user]).serialize + ) + end + + def test_changing_meta_key_with_meta_ooption + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}],"my_meta":{"size":1,"extra":42}}', + UserResource2.new([@user]).serialize(meta: {extra: 42}) + ) + end + + def test_changing_meta_keu_and_overriding_meta + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}],"my_meta":{"size":42}}', + UserResource2.new([@user]).serialize(meta: {size: 42}) + ) + end + + class UserResource3 + include Alba::Resource + + root_key :user, :users + + attributes :id, :name + + meta :my_meta # Change meta key only + end + + def test_changing_meta_key_only + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}],"my_meta":{"extra":42}}', + UserResource3.new([@user]).serialize(meta: {extra: 42}) + ) + end + + def test_changing_meta_key_and_eventually_no_meta + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}]}', + UserResource3.new([@user]).serialize + ) + end + + class UserResource4 + include Alba::Resource + + root_key :user, :users + + attributes :id, :name + + meta nil # Do not nest meta key + end + + def test_meta_without_nesting + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}],"extra":42}', + UserResource4.new([@user]).serialize(meta: {extra: 42}) + ) + end + + def test_meta_without_nesting_but_eventually_no_meta + assert_equal( + '{"users":[{"id":1,"name":"Masafumi OKURA"}]}', + UserResource4.new([@user]).serialize + ) + end end From d8200eb22910ada25ad9f4a11576993a8b9eb373 Mon Sep 17 00:00:00 2001 From: OKURA Masafumi Date: Thu, 21 Mar 2024 01:04:20 +0900 Subject: [PATCH 2/2] [Fix] Explicitly unfreeze string The latest Ruby warns about this. --- lib/alba/resource.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/alba/resource.rb b/lib/alba/resource.rb index c7c91ee..4562eb4 100644 --- a/lib/alba/resource.rb +++ b/lib/alba/resource.rb @@ -22,7 +22,7 @@ module Resource # @private def self.included(base) # rubocop:disable Metrics/MethodLength super - setup_method_body = 'private def _setup;' + setup_method_body = +'private def _setup;' base.class_eval do # Initialize INTERNAL_VARIABLES.each do |name, initial|