-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Allow Key Format to Be Overridden and Have Sensible Defaults #1029
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
Changes from all commits
234a90a
2ecbd8f
ff43a20
2a4564f
394a0ce
3db1b4f
d071f10
c2cfa4c
5dc5622
4c802c0
bc48d90
d2c16c3
d556f62
36dfa4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,3 +21,4 @@ tmp | |
*.swp | ||
.ruby-version | ||
.ruby-gemset | ||
tags |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -187,6 +187,38 @@ class PostSerializer < ActiveModel::Serializer | |
end | ||
``` | ||
|
||
### Overriding the Key Format | ||
|
||
You can specify that serializers use a different style for the format of the | ||
keys that are sent over. This can be done globally or at the controller action | ||
level. | ||
|
||
Each adapter has a default format, so typically you're either not going to have | ||
to change this, or you'll edit the global setting. | ||
|
||
For example, the JSON adapter defaults to `lower_camel` whereas the JSON API | ||
adapter defaults to `dasherize`. Any other adapter will default to `unaltered`. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the JSON API adapter should default to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @beauby I am very much in the other camp on that. The JSON API standard recommends dasherized keys and the couple JSON API JS libraries I've seen default to expecting incoming requests to be formatted with dasherized keys. In the vein of making this Just Work with JSON API, I think it should absolutely be dasherized. Otherwise almost everyone who uses it will need to add the global config option to their projects. I'll bow to the majority opinion, but I just wanted to voice my concern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, if JSON API recommends dashes, we should do dashes by default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, see #1029 (comment) and json-api/json-api#850 |
||
```ruby | ||
# Global | ||
ActiveModel::Serializer.config.key_format = :lower_camel | ||
|
||
# Per Controller Action | ||
class MyController < ActionController::Base | ||
def index | ||
render json: my_resource, | ||
key_format: :lower_camel | ||
end | ||
end | ||
``` | ||
|
||
#### Currently Supported Key Formats #### | ||
|
||
* `:unaltered` | ||
* `:lower_camel` | ||
* `:underscore` | ||
* `:dasherize` (aliased to `json_api`) | ||
|
||
### Built in Adapters | ||
|
||
#### FlattenJSON | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,6 +124,27 @@ def include_meta(json) | |
json[meta_key] = meta if meta | ||
json | ||
end | ||
|
||
def key_format | ||
instance_options[:key_format] || ActiveModel::Serializer.config.key_format || default_key_format | ||
end | ||
|
||
def format_key(formattable_key) | ||
case key_format | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assume we have namespaced object There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @timurvafin Do you have a ref for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
when :lower_camel | ||
formattable_key.to_s.camelize(:lower).to_sym | ||
when :dasherize, :json_api | ||
formattable_key.to_s.underscore.dasherize.to_sym | ||
when :underscore | ||
formattable_key.to_s.underscore.to_sym | ||
else | ||
formattable_key | ||
end | ||
end | ||
|
||
def default_key_format | ||
:unaltered | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ def initialize(serializer, options = {}) | |
|
||
def serializable_hash(options = nil) | ||
options ||= {} | ||
|
||
if serializer.respond_to?(:each) | ||
serializable_hash_for_collection(serializer, options) | ||
else | ||
|
@@ -28,6 +29,10 @@ def fragment_cache(cached_hash, non_cached_hash) | |
ActiveModel::Serializer::Adapter::JsonApi::FragmentCache.new.fragment_cache(root, cached_hash, non_cached_hash) | ||
end | ||
|
||
def default_key_format | ||
:dasherize | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome! Have you benchmarked the performance impact of mutating the hash by default? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep that would be cool 😄 not required for the PR itself, but I'm curious about it. That remembers me the Benchmark PR I had, I might need to pick that up again. |
||
end | ||
|
||
private | ||
|
||
ActiveModel.silence_warnings do | ||
|
@@ -85,7 +90,7 @@ def resource_identifier_for(serializer) | |
type = resource_identifier_type_for(serializer) | ||
id = resource_identifier_id_for(serializer) | ||
|
||
{ id: id.to_s, type: type } | ||
{ id: id.to_s, type: format_key(type).to_s } | ||
end | ||
|
||
def resource_object_for(serializer, options = {}) | ||
|
@@ -94,7 +99,15 @@ def resource_object_for(serializer, options = {}) | |
cache_check(serializer) do | ||
result = resource_identifier_for(serializer) | ||
attributes = serializer.attributes(options).except(:id) | ||
result[:attributes] = attributes if attributes.any? | ||
|
||
if attributes.any? | ||
attributes = attributes.each_with_object({}) do |(name, value), hash| | ||
hash[format_key(name)] = value | ||
end | ||
|
||
result[:attributes] = attributes | ||
end | ||
|
||
result | ||
end | ||
end | ||
|
@@ -120,7 +133,17 @@ def relationship_value_for(serializer, options = {}) | |
end | ||
|
||
def relationships_for(serializer) | ||
Hash[serializer.associations.map { |association| [association.key, { data: relationship_value_for(association.serializer, association.options) }] }] | ||
Hash[ | ||
serializer.associations.map do |association| | ||
[ | ||
format_key(association.key), | ||
{ | ||
data: relationship_value_for(association.serializer, | ||
association.options) | ||
} | ||
] | ||
end | ||
] | ||
end | ||
|
||
def included_for(serializer) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ module Configuration | |
base.config.array_serializer = ActiveModel::Serializer::ArraySerializer | ||
base.config.adapter = :flatten_json | ||
base.config.jsonapi_resource_type = :plural | ||
base.config.key_format = nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any particular reason to declare it as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joaomdmoura I just wanted to be explicit so that anyone spelunking in the code can easily look at this file and see what all the global configuration options are. I'm not tied to it if ya want me to remove it. |
||
end | ||
end | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
It would be awesome if along with this PR you could add some Docs to our new documentation we have being working on before release.
Maybe event add some article about integrating it with ember.js using our
How to
section.