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

Extract attributes filtering from serializer into adapter. #1232

Merged
merged 1 commit into from
Oct 5, 2015
Merged
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 @@ -23,6 +23,7 @@ Fixes:
- [#1214](https://github.com/rails-api/active_model_serializers/pull/1214) retrieve the key from the reflection options when building associations (@NullVoxPopuli, @hut8)

Misc:
- [#1232](https://github.com/rails-api/active_model_serializers/pull/1232) fields option no longer handled at serializer level (@beauby)
- [#1178](https://github.com/rails-api/active_model_serializers/pull/1178) env CAPTURE_STDERR=false lets devs see hard failures (@bf4)
- [#1177](https://github.com/rails-api/active_model_serializers/pull/1177) Remove Adapter autoloads in favor of require (@bf4)
- [#1117](https://github.com/rails-api/active_model_serializers/pull/1117) FlattenJson adapter no longer inherits Json adapter, renamed to Attributes (@bf4)
Expand Down
9 changes: 2 additions & 7 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,8 @@ def json_key
root || object.class.model_name.to_s.underscore
end

def attributes(options = {})
attributes =
if options[:fields]
self.class._attributes & options[:fields]
else
self.class._attributes.dup
end
def attributes
attributes = self.class._attributes.dup

attributes.each_with_object({}) do |name, hash|
unless self.class._fragmented
Expand Down
5 changes: 4 additions & 1 deletion lib/active_model/serializer/adapter/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ def include_meta(json)

def resource_object_for(options)
cache_check(serializer) do
serializer.attributes(options)
attributes = serializer.attributes
attributes.slice!(*options[:fields]) if options[:fields]
Copy link
Contributor

Choose a reason for hiding this comment

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

why did this need to be added?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is actually the main change of this PR: instead of being handled at serializer level, this is now handled at adapter level which allows for different format per adapter.

Copy link
Contributor

Choose a reason for hiding this comment

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

neato


attributes
end
end
end
Expand Down
30 changes: 15 additions & 15 deletions lib/active_model/serializer/adapter/json_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def initialize(serializer, options = {})

fields = options.delete(:fields)
if fields
@fieldset = ActiveModel::Serializer::Fieldset.new(fields, serializer.json_key)
@fieldset = ActiveModel::Serializer::Fieldset.new(fields)
else
@fieldset = options[:fieldset]
end
Expand All @@ -60,7 +60,7 @@ def serializable_hash(options = nil)
if serializer.respond_to?(:each)
serializable_hash_for_collection(options)
else
serializable_hash_for_single_resource(options)
serializable_hash_for_single_resource
end

ApiObjects::JsonApi.add!(hash)
Expand Down Expand Up @@ -99,8 +99,8 @@ def serializable_hash_for_collection(options)
hash
end

def serializable_hash_for_single_resource(options)
primary_data = primary_data_for(serializer, options)
def serializable_hash_for_single_resource
primary_data = primary_data_for(serializer)
relationships = relationships_for(serializer)
included = included_resources(@include_tree)
hash = { data: primary_data }
Expand Down Expand Up @@ -134,22 +134,22 @@ def resource_identifier_for(serializer)
{ id: id.to_s, type: type }
end

def resource_object_for(serializer, options = {})
options[:fields] = fieldset && fieldset.fields_for(serializer)

def resource_object_for(serializer)
cache_check(serializer) do
result = resource_identifier_for(serializer)
attributes = serializer.attributes(options).except(:id)
result[:attributes] = attributes if attributes.any?
result
resource_object = resource_identifier_for(serializer)
requested_fields = fieldset && fieldset.fields_for(resource_object[:type])
attributes = serializer.attributes.except(:id)
attributes.slice!(*requested_fields) if requested_fields
resource_object[:attributes] = attributes if attributes.any?
resource_object
end
end

def primary_data_for(serializer, options)
def primary_data_for(serializer)
if serializer.respond_to?(:each)
serializer.map { |s| resource_object_for(s, options) }
serializer.map { |s| resource_object_for(s) }
else
resource_object_for(serializer, options)
resource_object_for(serializer)
end
end

Expand Down Expand Up @@ -187,7 +187,7 @@ def add_included_resources_for(serializer, include_tree, included)
else
return unless serializer && serializer.object

primary_data = primary_data_for(serializer, instance_options)
primary_data = primary_data_for(serializer)
relationships = relationships_for(serializer)
primary_data[:relationships] = relationships if relationships.any?

Expand Down
17 changes: 4 additions & 13 deletions lib/active_model/serializer/fieldset.rb
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
module ActiveModel
class Serializer
class Fieldset
def initialize(fields, root = nil)
@root = root
def initialize(fields)
@raw_fields = fields
end

def fields
@fields ||= parsed_fields
end

def fields_for(serializer)
key = serializer.json_key
fields[key.to_sym] || fields[key.pluralize.to_sym]
def fields_for(type)
fields[type.singularize.to_sym] || fields[type.pluralize.to_sym]
end

private

ActiveModelSerializers.silence_warnings do
attr_reader :raw_fields, :root
attr_reader :raw_fields
end

def parsed_fields
if raw_fields.is_a?(Hash)
raw_fields.inject({}) { |h, (k, v)| h[k.to_sym] = v.map(&:to_sym); h }
elsif raw_fields.is_a?(Array)
if root.nil?
raise ArgumentError, 'The root argument must be specified if the fields argument is an array.'.freeze
end
hash = {}
hash[root.to_sym] = raw_fields.map(&:to_sym)
hash
else
{}
end
Expand Down
8 changes: 5 additions & 3 deletions test/adapter/json_api/collection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ def test_include_multiple_posts
end

def test_limiting_fields
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, fields: ['title'])

actual = ActiveModel::SerializableResource.new(
[@first_post, @second_post], adapter: :json_api,
fields: { posts: ['title'] })
.serializable_hash
expected = [
{
id: '1',
Expand All @@ -86,7 +88,7 @@ def test_limiting_fields
}
}
]
assert_equal(expected, @adapter.serializable_hash[:data])
assert_equal(expected, actual[:data])
end
end
end
Expand Down
5 changes: 0 additions & 5 deletions test/serializers/attributes_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ def test_attributes_definition
@profile_serializer.class._attributes)
end

def test_attributes_with_fields_option
assert_equal({ name: 'Name 1' },
@profile_serializer.attributes(fields: [:name]))
end

def test_attributes_inheritance_definition
assert_equal([:id, :body], @serializer_klass._attributes)
end
Expand Down
19 changes: 4 additions & 15 deletions test/serializers/fieldset_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,11 @@ module ActiveModel
class Serializer
class FieldsetTest < Minitest::Test
def test_fieldset_with_hash
fieldset = ActiveModel::Serializer::Fieldset.new({ 'post' => %w(id title), 'coment' => ['body'] })
fieldset = ActiveModel::Serializer::Fieldset.new('post' => %w(id title), 'comment' => ['body'])
expected = { :post => [:id, :title], :comment => [:body] }

assert_equal(
{ :post => [:id, :title], :coment => [:body] },
fieldset.fields
)
end

def test_fieldset_with_array_of_fields_and_root_name
fieldset = ActiveModel::Serializer::Fieldset.new(['title'], 'post')

assert_equal(
{ :post => [:title] },
fieldset.fields
)
assert_equal(expected, fieldset.fields)
end
end
end
end
end