Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespace separator setting for json-api and tests #1791

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Breaking changes:

Features:
- [#1609](https://github.com/rails-api/active_model_serializers/pull/1609) Adds JSON API Attribute namespace separator setting. (@youroff)
- [#1668](https://github.com/rails-api/active_model_serializers/pull/1668) Exclude nil and empty links. (@sigmike)
- [#1426](https://github.com/rails-api/active_model_serializers/pull/1426) Add ActiveModelSerializers.config.default_includes (@empact)

Expand Down
15 changes: 15 additions & 0 deletions docs/general/configuration_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ Possible values:
- `:singular`
- `:plural` (default)

##### jsonapi_namespace_separator

Sets separator string for namespaced models to render `type` attribute. Default value is `--`.

##### jsonapi_type_transform

Provides transform for `type` attribute. Class name `NicePost` gets converted into `nice_post`, `nice-post`, `NicePost` or `nicePost` depending on selected setting.

Possible values:

- `:underscore` (default)
- `:dashed`
- `:camel`
- `:snake`

##### jsonapi_include_toplevel_object

Include a [top level jsonapi member](http://jsonapi.org/format/#document-jsonapi-object)
Expand Down
2 changes: 2 additions & 0 deletions lib/active_model/serializer/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def config.array_serializer
config.default_includes = '*'
config.adapter = :attributes
config.jsonapi_resource_type = :plural
config.jsonapi_namespace_separator = '--'.freeze
config.jsonapi_type_transform = :underscore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type transform is underscore? doesn't this go against our other transform?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup... This is why it needs a thoughtful review :)

B mobile phone

On Jun 9, 2016, at 3:54 AM, L. Preston Sego III notifications@github.com wrote:

In lib/active_model/serializer/configuration.rb:

@@ -22,6 +22,8 @@ def config.array_serializer
config.default_includes = '*'
config.adapter = :attributes
config.jsonapi_resource_type = :plural

  •    config.jsonapi_namespace_separator = '--'.freeze
    
  •    config.jsonapi_type_transform = :underscore
    
    type transform is underscore? doesn't this go against our other transform?


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we had the default what it is now?

config.jsonapi_version = '1.0'
config.jsonapi_toplevel_meta = {}
# Make JSON API top-level jsonapi member opt-in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ def as_json

def type_for(serializer)
return serializer._type if serializer._type
if ActiveModelSerializers.config.jsonapi_resource_type == :singular
serializer.object.class.model_name.singular
else
serializer.object.class.model_name.plural
type = serializer.object.class.to_s.split('::')
type.map! { |t| KeyTransform.transform(t, ActiveModelSerializers.config.jsonapi_type_transform) }
type = type.join ActiveModelSerializers.config.jsonapi_namespace_separator
if ActiveModelSerializers.config.jsonapi_resource_type == :plural
type = type.pluralize
end
type
end

def id_for(serializer)
Expand Down
21 changes: 21 additions & 0 deletions lib/active_model_serializers/key_transform.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,26 @@ def underscore(value)
def unaltered(value)
value
end

# Transforms string to selected case
# Accepts string in any case: 'camel', 'undescore', 'dashed'.
#
# @example:
# transform('SomeClass', :underscore) => 'some_class'
# transform('some_class', :snake) => 'someClass'
# etc...
def transform(string, type)
string = string.underscore
case type.to_sym
when :dashed
string.dasherize
when :camel
string.camelize
when :snake
string.camelize(:lower)
else
string
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Is there a reason this doesn't leverage the existing transforms?
  • Why does there need to be a jsonapi_type_transform and a key_transform? Are there situations you'd really want them to differ?
  • Can type.map! ... from lib/active_model_serializers/adapter/json_api/resource_identifier.rb just use KeyTransform.send?
  • Isn't "snake (underscore)" snake_case, "camel (lower)" camelCase, and camel (pascal) CamelCase?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It pre-existed.. And fixing merge conflicts didn't fix feature dup. Am hoping someone to finish:)

B mobile phone

On Jun 9, 2016, at 9:16 PM, Ben Mills notifications@github.com wrote:

In lib/active_model_serializers/key_transform.rb:

  • transform('SomeClass', :underscore) => 'some_class'

  • transform('some_class', :snake) => 'someClass'

  • etc...

  • def transform(string, type)
  •  string = string.underscore
    
  •  case type.to_sym
    
  •  when :dashed
    
  •    string.dasherize
    
  •  when :camel
    
  •    string.camelize
    
  •  when :snake
    
  •    string.camelize(:lower)
    
  •  else
    
  •    string
    
  •  end
    
  • end
    Is there a reason this doesn't leverage the existing transforms?
    Why does there need to be a jsonapi_type_transform and a key_transform? Are there situations you'd really want them to differ?
    Can type.map! ... from lib/active_model_serializers/adapter/json_api/resource_identifier.rb just use KeyTransform.send?
    Isn't "snake (underscore)" snake_case, "camel (lower)" camelCase, and camel (pascal) CamelCase?

    You are receiving this because you authored the thread.
    Reply to this email directly, view it on GitHub, or mute the thread.

end
end
4 changes: 2 additions & 2 deletions test/adapter/json_api/linked_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ def test_underscore_model_namespace_for_linked_resource_type
expected = {
related: {
data: [{
type: 'spam-unrelated-links',
id: '456'
id: '456',
type: 'spam--unrelated-links'
}]
}
}
Expand Down
60 changes: 29 additions & 31 deletions test/adapter/json_api/resource_identifier_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,59 @@ def id
end

def test_defined_type
test_type(WithDefinedTypeSerializer, 'with-defined-type')
assert_identifier(WithDefinedTypeSerializer.new(@model), type: 'with-defined-type')
end

def test_singular_type
test_type_inflection(AuthorSerializer, 'author', :singular)
assert_with_confing(AuthorSerializer.new(@model), type: 'author', inflection: :singular)
end

def test_plural_type
test_type_inflection(AuthorSerializer, 'authors', :plural)
assert_with_confing(AuthorSerializer.new(@model), type: 'authors', inflection: :plural)
end

def test_type_with_namespace
spam = Spam::UnrelatedLink.new
assert_identifier(Spam::UnrelatedLinkSerializer.new(spam), type: 'spam--unrelated-links')
end

def test_type_with_custom_namespace
spam = Spam::UnrelatedLink.new
assert_with_confing(Spam::UnrelatedLinkSerializer.new(spam), type: 'spam/unrelated-links', namespace_separator: '/')
end

def test_id_defined_on_object
test_id(AuthorSerializer, @model.id.to_s)
assert_identifier(AuthorSerializer.new(@model), id: @model.id.to_s)
end

def test_id_defined_on_serializer
test_id(WithDefinedIdSerializer, 'special_id')
assert_identifier(WithDefinedIdSerializer.new(@model), id: 'special_id')
end

def test_id_defined_on_fragmented
test_id(FragmentedSerializer, 'special_id')
assert_identifier(WithDefinedIdSerializer.new(@model), id: 'special_id')
end

private

def test_type_inflection(serializer_class, expected_type, inflection)
original_inflection = ActiveModelSerializers.config.jsonapi_resource_type
ActiveModelSerializers.config.jsonapi_resource_type = inflection
test_type(serializer_class, expected_type)
def assert_with_confing(serializer, opts = {})
inflection = ActiveModelSerializers.config.jsonapi_resource_type
namespace_separator = ActiveModelSerializers.config.jsonapi_namespace_separator
ActiveModelSerializers.config.jsonapi_resource_type = opts.fetch(:inflection, inflection)
ActiveModelSerializers.config.jsonapi_namespace_separator = opts.fetch(:namespace_separator, namespace_separator)
assert_identifier(serializer, opts)
ensure
ActiveModelSerializers.config.jsonapi_resource_type = original_inflection
end

def test_type(serializer_class, expected_type)
serializer = serializer_class.new(@model)
resource_identifier = ResourceIdentifier.new(serializer, nil)
expected = {
id: @model.id.to_s,
type: expected_type
}

assert_equal(expected, resource_identifier.as_json)
ActiveModelSerializers.config.jsonapi_resource_type = inflection
ActiveModelSerializers.config.jsonapi_namespace_separator = namespace_separator
end

def test_id(serializer_class, id)
serializer = serializer_class.new(@model)
resource_identifier = ResourceIdentifier.new(serializer, nil)
inflection = ActiveModelSerializers.config.jsonapi_resource_type
type = @model.class.model_name.send(inflection)
def assert_identifier(serializer, opts = {})
identifier = ResourceIdentifier.new(serializer, opts)
expected = {
id: id,
type: type
id: opts.fetch(:id, identifier.as_json[:id]),
type: opts.fetch(:type, identifier.as_json[:type])
}

assert_equal(expected, resource_identifier.as_json)
assert_equal(expected, identifier.as_json)
end
end
end
Expand Down