Skip to content

Commit 3419a01

Browse files
authored
Merge pull request #2223 from rails-api/fields_support_in_all_adapters
Fieldset support in Attributes/JSON adapters
2 parents 7896ad6 + c77fdda commit 3419a01

File tree

5 files changed

+108
-4
lines changed

5 files changed

+108
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@ Breaking changes:
66

77
Features:
88

9+
- [#2327](https://github.com/rails-api/active_model_serializers/pull/2327) Add support for Ruby 2.6 on Travis CI (@wasifhossain)
10+
911
Fixes:
12+
1013
- [#2319](https://github.com/rails-api/active_model_serializers/pull/2319) Fixes #2316. (@kylekeesling)
11-
- Fix Rails 6.0 deprication warnings
12-
- update test fixture schema to use `timestamps` instead of `timestamp`
14+
- Fix Rails 6.0 deprication warnings
15+
- update test fixture schema to use `timestamps` instead of `timestamp`
16+
- [#2223](https://github.com/rails-api/active_model_serializers/pull/2223) Support Fieldset in Attributes/JSON adapters documented in [docs/general/fields.md](https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/fields.md) that worked partially before (@bf4)
1317

1418
Misc:
1519

lib/active_model/serializer.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ def associations(include_directive = ActiveModelSerializers.default_include_dire
365365
def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
366366
adapter_options ||= {}
367367
options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
368+
if (fieldset = adapter_options[:fieldset])
369+
options[:fields] = fieldset.fields_for(json_key)
370+
end
368371
resource = attributes_hash(adapter_options, options, adapter_instance)
369372
relationships = associations_hash(adapter_options, options, adapter_instance)
370373
resource.merge(relationships)
@@ -379,7 +382,12 @@ def as_json(adapter_opts = nil)
379382

380383
# Used by adapter as resource root.
381384
def json_key
382-
root || _type || object.class.model_name.to_s.underscore
385+
root || _type ||
386+
begin
387+
object.class.model_name.to_s.underscore
388+
rescue ArgumentError
389+
'anonymous_object'
390+
end
383391
end
384392

385393
def read_attribute_for_serialization(attr)

lib/active_model_serializers/adapter/attributes.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,34 @@
33
module ActiveModelSerializers
44
module Adapter
55
class Attributes < Base
6+
def initialize(*)
7+
super
8+
instance_options[:fieldset] ||= ActiveModel::Serializer::Fieldset.new(fields_to_fieldset(instance_options.delete(:fields)))
9+
end
10+
611
def serializable_hash(options = nil)
712
options = serialization_options(options)
813
options[:fields] ||= instance_options[:fields]
914
serialized_hash = serializer.serializable_hash(instance_options, options, self)
1015

1116
self.class.transform_key_casing!(serialized_hash, instance_options)
1217
end
18+
19+
private
20+
21+
def fields_to_fieldset(fields)
22+
return fields if fields.nil?
23+
resource_fields = []
24+
relationship_fields = {}
25+
fields.each do |field|
26+
case field
27+
when Symbol, String then resource_fields << field
28+
when Hash then relationship_fields.merge!(field)
29+
else fail ArgumentError, "Unknown conversion of fields to fieldset: '#{field.inspect}' in '#{fields.inspect}'"
30+
end
31+
end
32+
relationship_fields.merge!(serializer.json_key.to_sym => resource_fields)
33+
end
1334
end
1435
end
1536
end

test/adapter/json/fields_test.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
module ActiveModelSerializers
6+
module Adapter
7+
class Json
8+
class FieldsTest < ActiveSupport::TestCase
9+
class Post < ::Model
10+
attributes :title, :body
11+
associations :author, :comments
12+
end
13+
class Author < ::Model
14+
attributes :name, :birthday
15+
end
16+
class Comment < ::Model
17+
attributes :title, :body
18+
associations :author, :post
19+
end
20+
21+
class PostSerializer < ActiveModel::Serializer
22+
type 'post'
23+
attributes :title, :body
24+
belongs_to :author
25+
has_many :comments
26+
end
27+
28+
class AuthorSerializer < ActiveModel::Serializer
29+
attributes :name, :birthday
30+
end
31+
32+
class CommentSerializer < ActiveModel::Serializer
33+
type 'comment'
34+
attributes :title, :body
35+
belongs_to :author
36+
end
37+
38+
def setup
39+
@author = Author.new(id: 1, name: 'Lucas', birthday: '10.01.1990')
40+
@comment1 = Comment.new(id: 7, body: 'cool', author: @author)
41+
@comment2 = Comment.new(id: 12, body: 'awesome', author: @author)
42+
@post = Post.new(id: 1337, title: 'Title 1', body: 'Body 1',
43+
author: @author, comments: [@comment1, @comment2])
44+
@comment1.post = @post
45+
@comment2.post = @post
46+
end
47+
48+
def test_fields_attributes
49+
fields = [:title]
50+
hash = serializable(@post, adapter: :json, fields: fields, include: []).serializable_hash
51+
expected = { title: 'Title 1' }
52+
assert_equal(expected, hash[:post])
53+
end
54+
55+
def test_fields_included
56+
fields = [:title, { comments: [:body] }]
57+
hash = serializable(@post, adapter: :json, include: [:comments], fields: fields).serializable_hash
58+
expected = [{ body: @comment1.body }, { body: @comment2.body }]
59+
60+
assert_equal(expected, hash[:post][:comments])
61+
end
62+
end
63+
end
64+
end
65+
end

test/support/ruby_2_6_rails_4_2_patch.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ def recycle!
1313
end
1414
end
1515
else
16-
puts 'Monkeypatch for ActionController::TestResponse no longer needed'
16+
msg = 'Monkeypatch for ActionController::TestResponse not needed for '\
17+
'Rails 5+. We can drop this patch once we drop support for Rails < 5. '\
18+
"Current Rails version: #{ENV['RAILS_VERSION']}"
19+
20+
puts
21+
puts "\033[33m **** #{msg} **** \033[0m"
22+
puts
1723
end
1824
end

0 commit comments

Comments
 (0)