Skip to content

Commit

Permalink
Merge pull request #249 from okuramasafumi/as_json
Browse files Browse the repository at this point in the history
[Feat] Implement `as_json`
  • Loading branch information
okuramasafumi authored Oct 12, 2022
2 parents 18a9dc7 + f18aa18 commit 2475a3b
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 24 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.0.0]

### Breaking changes

- All Hash-related methods now return String key instead of Symbol key
This affects all users, but you can use `deep_symbolize_keys` in Rails environment if you prefer Symbol keys
Some DSLs that take key argument such as `on_nil` and `on_error`, are also affected

## [1.6.0] 2022-03-16

- [Feat] Support instance method as an attribute
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,15 @@ UserResource.new(user).serializable_hash
UserResource.new(user).to_h
```

If you want a Hash that corresponds to a JSON String returned by `serialize` method, you can use `as_json`.

```ruby
# These are equivalent and will return the same result
UserResource.new(user).serialize
UserResource.new(user).to_json
JSON.generate(UserResource.new(user).as_json)
```

### Inheritance

When you include `Alba::Resource` in your class, it's just a class so you can define any class that inherits from it. You can add new attributes to inherited class like below:
Expand Down
33 changes: 21 additions & 12 deletions lib/alba/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,26 @@ def initialize(object, params: {}, within: WITHIN_DEFAULT)
# @param meta [Hash] metadata for this seialization
# @return [String] serialized JSON string
def serialize(root_key: nil, meta: {})
key = root_key.nil? ? fetch_key : root_key
hash = if key && key != :''
h = {key.to_s => serializable_hash}
hash_with_metadata(h, meta)
else
serializable_hash
end
serialize_with(hash)
serialize_with(as_json(root_key: root_key, meta: meta))
end
alias to_json serialize

# Returns a Hash correspondng {Resource#serialize}
#
# @param root_key [Symbol, nil, true]
# @param meta [Hash] metadata for this seialization
# @param symbolize_root_key [Boolean] determines if root key should be symbolized
# @return [Hash]
def as_json(root_key: nil, meta: {})
key = root_key.nil? ? fetch_key : root_key.to_s
if key && !key.empty?
h = {key => serializable_hash}
hash_with_metadata(h, meta)
else
serializable_hash
end
end

# A Hash for serialization
#
# @return [Hash]
Expand Down Expand Up @@ -98,10 +107,10 @@ def serializable_hash_for_collection
end
end

# @return [Symbol]
# @return [String]
def fetch_key
k = collection? ? _key_for_collection : _key
transforming_root_key? ? transform_key(k) : k.to_sym
transforming_root_key? ? transform_key(k) : k
end

def _key_for_collection
Expand Down Expand Up @@ -190,7 +199,7 @@ def handle_error(error, object, key, attribute, hash)
# @return [Symbol]
def transform_key(key) # rubocop:disable Metrics/CyclomaticComplexity
key = key.to_s
return key.to_sym if @_transform_type == :none || key.empty? # We can skip transformation
return key if @_transform_type == :none || key.empty? # We can skip transformation

inflector = Alba.inflector
raise Alba::Error, 'Inflector is nil. You can set inflector with `Alba.enable_inference!(with: :active_support)` for example.' unless inflector
Expand All @@ -200,7 +209,7 @@ def transform_key(key) # rubocop:disable Metrics/CyclomaticComplexity
when :lower_camel then inflector.camelize_lower(key)
when :dash then inflector.dasherize(key)
when :snake then inflector.underscore(key)
end.to_sym
end
end

def fetch_attribute(object, key, attribute) # rubocop:disable Metrics/CyclomaticComplexity
Expand Down
6 changes: 3 additions & 3 deletions test/alba_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ def test_it_serializes_object_with_fully_inlined_definitions_with_oj
def test_it_works_with_oj_default_backend
Alba.backend = :oj_default

Oj.default_options = { mode: :object }
Oj.default_options = {mode: :object}
assert_equal(
'{"foo":{":id":1}}',
'{"foo":{"id":1}}',
Alba.serialize(@user, root_key: :foo) do
attributes :id
end
)

Oj.default_options = { mode: :compat }
Oj.default_options = {mode: :compat}
assert_equal(
'{"foo":{"id":1}}',
Alba.serialize(@user, root_key: :foo) do
Expand Down
24 changes: 17 additions & 7 deletions test/resource_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,25 @@ def bar_size(foo)
end
end

def setup
@foo = Foo.new
@foo.id = 1
@bar = Bar.new
@bar.id = 1
@foo.bars = [@bar]
end

def test_as_json
assert_equal(
{'foo' => {'id' => 1, 'bar_size' => 1, 'bars' => [{'id' => 1}]}},
FooResource.new(@foo).as_json
)
end

def test_serializable_hash
foo = Foo.new
foo.id = 1
bar = Bar.new
bar.id = 1
foo.bars = [bar]
assert_equal(
{id: 1, bar_size: 1, bars: [{id: 1}]},
FooResource.new(foo).serializable_hash
{'id' => 1, 'bar_size' => 1, 'bars' => [{'id' => 1}]},
FooResource.new(@foo).serializable_hash
)
end
end
4 changes: 2 additions & 2 deletions test/usecases/nil_handler_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def test_nil_handler_always_returning_empty_string

class ProfileResource2 < ProfileResource
on_nil do |_object, key, _attribute|
if key == :full_name
if key == 'full_name'
'Unknown'
else
''
Expand All @@ -123,7 +123,7 @@ class ProfileResource2 < ProfileResource

class UserResource2 < UserResource
on_nil do |object, key, _attribute|
case key
case key.to_sym
when :age
20
when :profile
Expand Down

0 comments on commit 2475a3b

Please sign in to comment.