Skip to content

Commit 0d1f770

Browse files
committed
Merge pull request #1494 from bf4/serializable_serializer
Make serializers serializable, step 1.
2 parents b6343a5 + b169ed3 commit 0d1f770

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
Breaking changes:
44

55
Features:
6+
- [#1494](https://github.com/rails-api/active_model_serializers/pull/1494) Make serializers serializalbe
7+
(using the Attributes adapter by default). (@bf4)
68
- [#1550](https://github.com/rails-api/active_model_serializers/pull/1550) Add
79
Rails url_helpers to `SerializationContext` for use in links. (@remear, @bf4)
810
- [#1004](https://github.com/rails-api/active_model_serializers/pull/1004) JSON API errors object implementation.

lib/active_model/serializer.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,57 @@ def success?
126126
true
127127
end
128128

129+
# @return [Hash] containing the attributes and first level
130+
# associations, similar to how ActiveModel::Serializers::JSON is used
131+
# in ActiveRecord::Base.
132+
#
133+
# TODO: Move to here the Attributes adapter logic for
134+
# +serializable_hash_for_single_resource(options)+
135+
# and include <tt>ActiveModel::Serializers::JSON</tt>.
136+
# So that the below is true:
137+
# @param options [nil, Hash] The same valid options passed to `serializable_hash`
138+
# (:only, :except, :methods, and :include).
139+
#
140+
# See
141+
# https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serializers/json.rb#L17-L101
142+
# https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serialization.rb#L85-L123
143+
# https://github.com/rails/rails/blob/v5.0.0.beta2/activerecord/lib/active_record/serialization.rb#L11-L17
144+
# https://github.com/rails/rails/blob/v5.0.0.beta2/activesupport/lib/active_support/core_ext/object/json.rb#L147-L162
145+
#
146+
# @example
147+
# # The :only and :except options can be used to limit the attributes included, and work
148+
# # similar to the attributes method.
149+
# serializer.as_json(only: [:id, :name])
150+
# serializer.as_json(except: [:id, :created_at, :age])
151+
#
152+
# # To include the result of some method calls on the model use :methods:
153+
# serializer.as_json(methods: :permalink)
154+
#
155+
# # To include associations use :include:
156+
# serializer.as_json(include: :posts)
157+
# # Second level and higher order associations work as well:
158+
# serializer.as_json(include: { posts: { include: { comments: { only: :body } }, only: :title } })
159+
def serializable_hash(adapter_opts = nil)
160+
adapter_opts ||= {}
161+
adapter_opts = { include: '*', adapter: :attributes }.merge!(adapter_opts)
162+
adapter = ActiveModelSerializers::Adapter.create(self, adapter_opts)
163+
adapter.serializable_hash(adapter_opts)
164+
end
165+
alias to_hash serializable_hash
166+
alias to_h serializable_hash
167+
168+
# @see #serializable_hash
169+
# TODO: When moving attributes adapter logic here, @see #serializable_hash
170+
# So that the below is true:
171+
# @param options [nil, Hash] The same valid options passed to `as_json`
172+
# (:root, :only, :except, :methods, and :include).
173+
# The default for `root` is nil.
174+
# The default value for include_root is false. You can change it to true if the given
175+
# JSON string includes a single root node.
176+
def as_json(adapter_opts = nil)
177+
serializable_hash(adapter_opts)
178+
end
179+
129180
# Used by adapter as resource root.
130181
def json_key
131182
root || object.class.model_name.to_s.underscore
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
module ActiveModel
2+
class Serializer
3+
class SerializationTest < ActiveSupport::TestCase
4+
class Blog < ActiveModelSerializers::Model
5+
attr_accessor :id, :name, :authors
6+
end
7+
class Author < ActiveModelSerializers::Model
8+
attr_accessor :id, :name
9+
end
10+
class BlogSerializer < ActiveModel::Serializer
11+
attributes :id
12+
attribute :name, key: :title
13+
14+
has_many :authors
15+
end
16+
class AuthorSerializer < ActiveModel::Serializer
17+
attributes :id, :name
18+
end
19+
20+
setup do
21+
@authors = [Author.new(id: 1, name: 'Blog Author')]
22+
@blog = Blog.new(id: 2, name: 'The Blog', authors: @authors)
23+
@serializer_instance = BlogSerializer.new(@blog)
24+
@serializable = ActiveModel::SerializableResource.new(@blog, serializer: BlogSerializer, adapter: :attributes)
25+
@expected_hash = { id: 2, title: 'The Blog', authors: [{ id: 1, name: 'Blog Author' }] }
26+
@expected_json = '{"id":2,"title":"The Blog","authors":[{"id":1,"name":"Blog Author"}]}'
27+
end
28+
29+
test '#serializable_hash is the same as generated by the attributes adapter' do
30+
assert_equal @serializable.serializable_hash, @serializer_instance.serializable_hash
31+
assert_equal @expected_hash, @serializer_instance.serializable_hash
32+
end
33+
34+
test '#as_json is the same as generated by the attributes adapter' do
35+
assert_equal @serializable.as_json, @serializer_instance.as_json
36+
assert_equal @expected_hash, @serializer_instance.as_json
37+
end
38+
39+
test '#to_json is the same as generated by the attributes adapter' do
40+
assert_equal @serializable.to_json, @serializer_instance.to_json
41+
assert_equal @expected_json, @serializer_instance.to_json
42+
end
43+
44+
test '#to_h is an alias for #serializable_hash' do
45+
assert_equal @serializable.serializable_hash, @serializer_instance.to_h
46+
assert_equal @expected_hash, @serializer_instance.to_h
47+
end
48+
49+
test '#to_hash is an alias for #serializable_hash' do
50+
assert_equal @serializable.serializable_hash, @serializer_instance.to_hash
51+
assert_equal @expected_hash, @serializer_instance.to_hash
52+
end
53+
end
54+
end
55+
end

0 commit comments

Comments
 (0)