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..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| @@ -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