-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Optional fields in associations (priority on serializer) #1628
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
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 |
---|---|---|
|
@@ -3,7 +3,9 @@ module Adapter | |
class Attributes < Base | ||
def initialize(serializer, options = {}) | ||
super | ||
@include_tree = ActiveModel::Serializer::IncludeTree.from_include_args(options[:include] || '*') | ||
@include_tree = ActiveModel::Serializer::IncludeTree.from_include_args( | ||
options[:include] || ActiveModel::Serializer.config.attributes_adapter_include_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. this is a separate feature, no? |
||
@cached_attributes = options[:cache_attributes] || {} | ||
end | ||
|
||
|
@@ -60,8 +62,11 @@ def serializable_hash_for_single_resource(options) | |
|
||
def resource_relationships(options) | ||
relationships = {} | ||
|
||
serializer.associations(@include_tree).each do |association| | ||
relationships[association.key] = relationship_value_for(association, options) | ||
relationships[association.key] = relationship_value_for( | ||
association, options | ||
) | ||
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 know this is just cosmetic, am curious what you like about it |
||
end | ||
|
||
relationships | ||
|
@@ -71,8 +76,21 @@ def relationship_value_for(association, options) | |
return association.options[:virtual_value] if association.options[:virtual_value] | ||
return unless association.serializer && association.serializer.object | ||
|
||
if options[:fields].is_a? Array | ||
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. this snippet of code is somewhat problematic.. I believe what it says is
I think this could be rewritten as fields = Array(options[:fields]).lazy.select {|elem| elem.respond_to?(:keys) }.take(1).map {|elem| association.name }.force.compact.first Would be nice for this to be tested separately or have a descriptive name so it's easier to follow what it's doing, as well :) 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 you might also be able to use the |
||
fields = options[:fields].select do |k| #I would prefer using {...} here but RuboCop fails :/ | ||
k.is_a? Hash | ||
end.try(:first).try(:[], association.name) | ||
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.
Yeah, we're using Rails-style block semantics :) 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. How about the following: fields = options[:fields]
.select { |k| k.is_a? Hash }
.try(:[], association.name) |
||
end | ||
|
||
opts = instance_options.merge(include: @include_tree[association.key]) | ||
Attributes.new(association.serializer, opts).serializable_hash(options) | ||
options = options.merge(fields: fields) | ||
|
||
Attributes.new( | ||
association.serializer, | ||
opts.merge(association.options) | ||
).serializable_hash( | ||
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. we need to rename internal apis like 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. (just thinking aloud. not actionable here) |
||
options.merge(association.options) | ||
) | ||
end | ||
|
||
# no-op: Attributes adapter does not include meta data, because it does not support root. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,6 +84,72 @@ def test_include_option | |
|
||
assert_equal(expected, actual) | ||
end | ||
|
||
def test_fields_option | ||
serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_post, @second_post]) | ||
adapter = ActiveModelSerializers::Adapter::Json.new(serializer) | ||
actual = adapter.serializable_hash(fields: [:id]) | ||
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. these options should be passed into the adapter. most conventional way to do it is actual = serializable([@first_post, @second_post], adapter: :json, fields: [:id]).serializable_hash see #1643 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. Also, since |
||
|
||
expected = { posts: [{ | ||
id: 1, | ||
comments: [], | ||
author: { | ||
id: 1, | ||
name: 'Steve K.' | ||
}, | ||
blog: { | ||
id: 999, | ||
name: 'Custom blog' | ||
} | ||
}, { | ||
id: 2, | ||
comments: [], | ||
author: { | ||
id: 1, | ||
name: 'Steve K.' | ||
}, | ||
blog: { | ||
id: 999, | ||
name: 'Custom blog' | ||
} | ||
}] } | ||
|
||
assert_equal(expected, actual) | ||
end | ||
|
||
def test_fields_with_no_associations_include_option | ||
serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_post, @second_post]) | ||
adapter = ActiveModelSerializers::Adapter::Json.new(serializer, include: []) | ||
actual = adapter.serializable_hash(fields: [:id]) | ||
|
||
expected = { posts: [{ | ||
id: 1 | ||
}, { | ||
id: 2 | ||
}] } | ||
|
||
assert_equal(expected, actual) | ||
end | ||
|
||
def test_fields_with_associations_fields_option | ||
serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_post, @second_post]) | ||
adapter = ActiveModelSerializers::Adapter::Json.new(serializer, include: [:author]) | ||
actual = adapter.serializable_hash(fields: [:id, author: [:name]]) | ||
|
||
expected = { posts: [{ | ||
id: 1, | ||
author: { | ||
name: 'Steve K.' | ||
} | ||
}, { | ||
id: 2, | ||
author: { | ||
name: 'Steve K.' | ||
} | ||
}] } | ||
|
||
assert_equal(expected, actual) | ||
end | ||
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.
I'm guessing we should rename this variable to
field_options
so it's clear where it's coming from. It took me a moment.