Skip to content

Commit

Permalink
Merge pull request #362 from okuramasafumi/meta-key
Browse files Browse the repository at this point in the history
[Feat] Add the ability to change key for metadata
  • Loading branch information
okuramasafumi committed Mar 21, 2024
2 parents 48f5a04 + d8200eb commit 2f0bfe5
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 6 deletions.
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 15 additions & 6 deletions lib/alba/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand Down Expand Up @@ -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|
Expand Down Expand Up @@ -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
Expand Down
85 changes: 85 additions & 0 deletions test/usecases/meta_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 2f0bfe5

Please sign in to comment.