active_model_serializers 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/README.textile +558 -0
- data/Rakefile +13 -0
- data/active_model_serializers.gemspec +18 -0
- data/lib/action_controller/serialization.rb +52 -0
- data/lib/active_model/serializer.rb +353 -0
- data/lib/active_model_serializers.rb +48 -0
- data/lib/generators/serializer/USAGE +9 -0
- data/lib/generators/serializer/serializer_generator.rb +41 -0
- data/lib/generators/serializer/templates/serializer.rb +9 -0
- data/test/generators_test.rb +67 -0
- data/test/serialization_test.rb +186 -0
- data/test/serializer_support_test.rb +11 -0
- data/test/serializer_test.rb +787 -0
- data/test/test_helper.rb +24 -0
- metadata +92 -0
@@ -0,0 +1,9 @@
|
|
1
|
+
Description:
|
2
|
+
Generates a serializer for the given resource with tests.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
`rails generate serializer Account name created_at`
|
6
|
+
|
7
|
+
For TestUnit it creates:
|
8
|
+
Serializer: app/serializers/account_serializer.rb
|
9
|
+
TestUnit: test/unit/account_serializer_test.rb
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rails
|
2
|
+
module Generators
|
3
|
+
class SerializerGenerator < NamedBase
|
4
|
+
source_root File.expand_path("../templates", __FILE__)
|
5
|
+
check_class_collision :suffix => "Serializer"
|
6
|
+
|
7
|
+
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
8
|
+
|
9
|
+
class_option :parent, :type => :string, :desc => "The parent class for the generated serializer"
|
10
|
+
|
11
|
+
def create_serializer_file
|
12
|
+
template 'serializer.rb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
# hook_for :test_framework
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def attributes_names
|
20
|
+
attributes.select { |attr| !attr.reference? }.map { |a| a.name.to_sym }
|
21
|
+
end
|
22
|
+
|
23
|
+
def association_names
|
24
|
+
attributes.select { |attr| attr.reference? }.map { |a| a.name.to_sym }
|
25
|
+
end
|
26
|
+
|
27
|
+
def parent_class_name
|
28
|
+
if options[:parent]
|
29
|
+
options[:parent]
|
30
|
+
# Only works on 3.2
|
31
|
+
# elsif (n = Rails::Generators.namespace) && n.const_defined?(:ApplicationSerializer)
|
32
|
+
# "ApplicationSerializer"
|
33
|
+
elsif Object.const_defined?(:ApplicationSerializer)
|
34
|
+
"ApplicationSerializer"
|
35
|
+
else
|
36
|
+
"ActiveModel::Serializer"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% module_namespacing do -%>
|
2
|
+
class <%= class_name %>Serializer < <%= parent_class_name %>
|
3
|
+
<% if attributes.any? -%> attributes <%= attributes_names.map(&:inspect).join(", ") %>
|
4
|
+
<% end -%>
|
5
|
+
<% association_names.each do |attribute| -%>
|
6
|
+
has_one :<%= attribute %>
|
7
|
+
<% end -%>
|
8
|
+
end
|
9
|
+
<% end -%>
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Foo < Rails::Application
|
4
|
+
end
|
5
|
+
|
6
|
+
Rails.application.load_generators
|
7
|
+
|
8
|
+
require 'generators/serializer/serializer_generator'
|
9
|
+
|
10
|
+
class SerializerGeneratorTest < Rails::Generators::TestCase
|
11
|
+
destination File.expand_path("../tmp", __FILE__)
|
12
|
+
setup :prepare_destination
|
13
|
+
|
14
|
+
tests Rails::Generators::SerializerGenerator
|
15
|
+
arguments %w(account name:string description:text business:references)
|
16
|
+
|
17
|
+
def test_generates_a_serializer
|
18
|
+
run_generator
|
19
|
+
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < ActiveModel::Serializer/
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_generates_a_namespaced_serializer
|
23
|
+
run_generator ["admin/account"]
|
24
|
+
assert_file "app/serializers/admin/account_serializer.rb", /class Admin::AccountSerializer < ActiveModel::Serializer/
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_uses_application_serializer_if_one_exists
|
28
|
+
Object.const_set(:ApplicationSerializer, Class.new)
|
29
|
+
run_generator
|
30
|
+
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < ApplicationSerializer/
|
31
|
+
ensure
|
32
|
+
Object.send :remove_const, :ApplicationSerializer
|
33
|
+
end
|
34
|
+
|
35
|
+
# def test_uses_namespace_application_serializer_if_one_exists
|
36
|
+
# Object.const_set(:SerializerNamespace, Module.new)
|
37
|
+
# SerializerNamespace.const_set(:ApplicationSerializer, Class.new)
|
38
|
+
# Rails::Generators.namespace = SerializerNamespace
|
39
|
+
# run_generator
|
40
|
+
# assert_file "app/serializers/serializer_namespace/account_serializer.rb",
|
41
|
+
# /module SerializerNamespace\n class AccountSerializer < ApplicationSerializer/
|
42
|
+
# ensure
|
43
|
+
# Object.send :remove_const, :SerializerNamespace
|
44
|
+
# Rails::Generators.namespace = nil
|
45
|
+
# end
|
46
|
+
|
47
|
+
def test_uses_given_parent
|
48
|
+
Object.const_set(:ApplicationSerializer, Class.new)
|
49
|
+
run_generator ["Account", "--parent=MySerializer"]
|
50
|
+
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < MySerializer/
|
51
|
+
ensure
|
52
|
+
Object.send :remove_const, :ApplicationSerializer
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_generates_attributes_and_associations
|
56
|
+
run_generator
|
57
|
+
assert_file "app/serializers/account_serializer.rb" do |serializer|
|
58
|
+
assert_match(/^ attributes :name, :description$/, serializer)
|
59
|
+
assert_match(/^ has_one :business$/, serializer)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_with_no_attributes_does_not_add_extra_space
|
64
|
+
run_generator ["account"]
|
65
|
+
assert_file "app/serializers/account_serializer.rb", /class AccountSerializer < ActiveModel::Serializer\nend/
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
class RenderJsonTest < ActionController::TestCase
|
5
|
+
class JsonRenderable
|
6
|
+
def as_json(options={})
|
7
|
+
hash = { :a => :b, :c => :d, :e => :f }
|
8
|
+
hash.except!(*options[:except]) if options[:except]
|
9
|
+
hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_json(options = {})
|
13
|
+
super :except => [:c, :e]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class JsonSerializer
|
18
|
+
def initialize(object, scope, options={})
|
19
|
+
@object, @scope, @options = object, scope, options
|
20
|
+
end
|
21
|
+
|
22
|
+
def as_json(*)
|
23
|
+
hash = { :object => @object.as_json, :scope => @scope.as_json }
|
24
|
+
hash.merge!(:options => true) if @options[:options]
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class JsonSerializable
|
30
|
+
def initialize(skip=false)
|
31
|
+
@skip = skip
|
32
|
+
end
|
33
|
+
|
34
|
+
def active_model_serializer
|
35
|
+
JsonSerializer unless @skip
|
36
|
+
end
|
37
|
+
|
38
|
+
def as_json(*)
|
39
|
+
{ :serializable_object => true }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class TestController < ActionController::Base
|
44
|
+
protect_from_forgery
|
45
|
+
|
46
|
+
serialization_scope :current_user
|
47
|
+
attr_reader :current_user
|
48
|
+
|
49
|
+
def self.controller_path
|
50
|
+
'test'
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_json_nil
|
54
|
+
render :json => nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def render_json_render_to_string
|
58
|
+
render :text => render_to_string(:json => '[]')
|
59
|
+
end
|
60
|
+
|
61
|
+
def render_json_hello_world
|
62
|
+
render :json => ActiveSupport::JSON.encode(:hello => 'world')
|
63
|
+
end
|
64
|
+
|
65
|
+
def render_json_hello_world_with_status
|
66
|
+
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :status => 401
|
67
|
+
end
|
68
|
+
|
69
|
+
def render_json_hello_world_with_callback
|
70
|
+
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
|
71
|
+
end
|
72
|
+
|
73
|
+
def render_json_with_custom_content_type
|
74
|
+
render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
|
75
|
+
end
|
76
|
+
|
77
|
+
def render_symbol_json
|
78
|
+
render :json => ActiveSupport::JSON.encode(:hello => 'world')
|
79
|
+
end
|
80
|
+
|
81
|
+
def render_json_with_extra_options
|
82
|
+
render :json => JsonRenderable.new, :except => [:c, :e]
|
83
|
+
end
|
84
|
+
|
85
|
+
def render_json_without_options
|
86
|
+
render :json => JsonRenderable.new
|
87
|
+
end
|
88
|
+
|
89
|
+
def render_json_with_serializer
|
90
|
+
@current_user = Struct.new(:as_json).new(:current_user => true)
|
91
|
+
render :json => JsonSerializable.new
|
92
|
+
end
|
93
|
+
|
94
|
+
def render_json_with_serializer_and_options
|
95
|
+
@current_user = Struct.new(:as_json).new(:current_user => true)
|
96
|
+
render :json => JsonSerializable.new, :options => true
|
97
|
+
end
|
98
|
+
|
99
|
+
def render_json_with_serializer_api_but_without_serializer
|
100
|
+
@current_user = Struct.new(:as_json).new(:current_user => true)
|
101
|
+
render :json => JsonSerializable.new(true)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
tests TestController
|
106
|
+
|
107
|
+
def setup
|
108
|
+
# enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
|
109
|
+
# a more accurate simulation of what happens in "real life".
|
110
|
+
super
|
111
|
+
@controller.logger = Logger.new(nil)
|
112
|
+
|
113
|
+
@request.host = "www.nextangle.com"
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_render_json_nil
|
117
|
+
get :render_json_nil
|
118
|
+
assert_equal 'null', @response.body
|
119
|
+
assert_equal 'application/json', @response.content_type
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_render_json_render_to_string
|
123
|
+
get :render_json_render_to_string
|
124
|
+
assert_equal '[]', @response.body
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
def test_render_json
|
129
|
+
get :render_json_hello_world
|
130
|
+
assert_equal '{"hello":"world"}', @response.body
|
131
|
+
assert_equal 'application/json', @response.content_type
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_render_json_with_status
|
135
|
+
get :render_json_hello_world_with_status
|
136
|
+
assert_equal '{"hello":"world"}', @response.body
|
137
|
+
assert_equal 401, @response.status
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_render_json_with_callback
|
141
|
+
get :render_json_hello_world_with_callback
|
142
|
+
assert_equal 'alert({"hello":"world"})', @response.body
|
143
|
+
assert_equal 'application/json', @response.content_type
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_render_json_with_custom_content_type
|
147
|
+
get :render_json_with_custom_content_type
|
148
|
+
assert_equal '{"hello":"world"}', @response.body
|
149
|
+
assert_equal 'text/javascript', @response.content_type
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_render_symbol_json
|
153
|
+
get :render_symbol_json
|
154
|
+
assert_equal '{"hello":"world"}', @response.body
|
155
|
+
assert_equal 'application/json', @response.content_type
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_render_json_forwards_extra_options
|
159
|
+
get :render_json_with_extra_options
|
160
|
+
assert_equal '{"a":"b"}', @response.body
|
161
|
+
assert_equal 'application/json', @response.content_type
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_render_json_calls_to_json_from_object
|
165
|
+
get :render_json_without_options
|
166
|
+
assert_equal '{"a":"b"}', @response.body
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_render_json_with_serializer
|
170
|
+
get :render_json_with_serializer
|
171
|
+
assert_match '"scope":{"current_user":true}', @response.body
|
172
|
+
assert_match '"object":{"serializable_object":true}', @response.body
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_render_json_with_serializer_and_options
|
176
|
+
get :render_json_with_serializer_and_options
|
177
|
+
assert_match '"scope":{"current_user":true}', @response.body
|
178
|
+
assert_match '"object":{"serializable_object":true}', @response.body
|
179
|
+
assert_match '"options":true', @response.body
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_render_json_with_serializer_api_but_without_serializer
|
183
|
+
get :render_json_with_serializer_api_but_without_serializer
|
184
|
+
assert_match '{"serializable_object":true}', @response.body
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class RandomModel
|
4
|
+
include ActiveModel::SerializerSupport
|
5
|
+
end
|
6
|
+
|
7
|
+
class SerializerSupportTest < ActiveModel::TestCase
|
8
|
+
test "it returns nil if no serializer exists" do
|
9
|
+
assert_equal nil, RandomModel.new.active_model_serializer
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,787 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class SerializerTest < ActiveModel::TestCase
|
4
|
+
class Model
|
5
|
+
def initialize(hash={})
|
6
|
+
@attributes = hash
|
7
|
+
end
|
8
|
+
|
9
|
+
def read_attribute_for_serialization(name)
|
10
|
+
@attributes[name]
|
11
|
+
end
|
12
|
+
|
13
|
+
def as_json(*)
|
14
|
+
{ :model => "Model" }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class User
|
19
|
+
include ActiveModel::SerializerSupport
|
20
|
+
|
21
|
+
attr_accessor :superuser
|
22
|
+
|
23
|
+
def initialize(hash={})
|
24
|
+
@attributes = hash.merge(:first_name => "Jose", :last_name => "Valim", :password => "oh noes yugive my password")
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_attribute_for_serialization(name)
|
28
|
+
@attributes[name]
|
29
|
+
end
|
30
|
+
|
31
|
+
def super_user?
|
32
|
+
@superuser
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Post < Model
|
37
|
+
def initialize(attributes)
|
38
|
+
super(attributes)
|
39
|
+
self.comments ||= []
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor :comments
|
43
|
+
def active_model_serializer; PostSerializer; end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Comment < Model
|
47
|
+
def active_model_serializer; CommentSerializer; end
|
48
|
+
end
|
49
|
+
|
50
|
+
class UserSerializer < ActiveModel::Serializer
|
51
|
+
attributes :first_name, :last_name
|
52
|
+
|
53
|
+
def serializable_hash
|
54
|
+
attributes.merge(:ok => true).merge(scope)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class DefaultUserSerializer < ActiveModel::Serializer
|
59
|
+
attributes :first_name, :last_name
|
60
|
+
end
|
61
|
+
|
62
|
+
class MyUserSerializer < ActiveModel::Serializer
|
63
|
+
attributes :first_name, :last_name
|
64
|
+
|
65
|
+
def serializable_hash
|
66
|
+
hash = attributes
|
67
|
+
hash = hash.merge(:super_user => true) if my_user.super_user?
|
68
|
+
hash
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class CommentSerializer
|
73
|
+
def initialize(comment, scope, options={})
|
74
|
+
@comment, @scope = comment, scope
|
75
|
+
end
|
76
|
+
|
77
|
+
def serializable_hash
|
78
|
+
{ :title => @comment.read_attribute_for_serialization(:title) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def as_json(options=nil)
|
82
|
+
options ||= {}
|
83
|
+
if options[:root] == false
|
84
|
+
serializable_hash
|
85
|
+
else
|
86
|
+
{ :comment => serializable_hash }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class PostSerializer < ActiveModel::Serializer
|
92
|
+
attributes :title, :body
|
93
|
+
has_many :comments, :serializer => CommentSerializer
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_attributes
|
97
|
+
user = User.new
|
98
|
+
user_serializer = DefaultUserSerializer.new(user, {})
|
99
|
+
|
100
|
+
hash = user_serializer.as_json
|
101
|
+
|
102
|
+
assert_equal({
|
103
|
+
:default_user => { :first_name => "Jose", :last_name => "Valim" }
|
104
|
+
}, hash)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_attributes_method
|
108
|
+
user = User.new
|
109
|
+
user_serializer = UserSerializer.new(user, {})
|
110
|
+
|
111
|
+
hash = user_serializer.as_json
|
112
|
+
|
113
|
+
assert_equal({
|
114
|
+
:user => { :first_name => "Jose", :last_name => "Valim", :ok => true }
|
115
|
+
}, hash)
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_serializer_receives_scope
|
119
|
+
user = User.new
|
120
|
+
user_serializer = UserSerializer.new(user, {:scope => true})
|
121
|
+
|
122
|
+
hash = user_serializer.as_json
|
123
|
+
|
124
|
+
assert_equal({
|
125
|
+
:user => {
|
126
|
+
:first_name => "Jose",
|
127
|
+
:last_name => "Valim",
|
128
|
+
:ok => true,
|
129
|
+
:scope => true
|
130
|
+
}
|
131
|
+
}, hash)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_pretty_accessors
|
135
|
+
user = User.new
|
136
|
+
user.superuser = true
|
137
|
+
user_serializer = MyUserSerializer.new(user, nil)
|
138
|
+
|
139
|
+
hash = user_serializer.as_json
|
140
|
+
|
141
|
+
assert_equal({
|
142
|
+
:my_user => {
|
143
|
+
:first_name => "Jose", :last_name => "Valim", :super_user => true
|
144
|
+
}
|
145
|
+
}, hash)
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_has_many
|
149
|
+
user = User.new
|
150
|
+
|
151
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
|
152
|
+
comments = [Comment.new(:title => "Comment1"), Comment.new(:title => "Comment2")]
|
153
|
+
post.comments = comments
|
154
|
+
|
155
|
+
post_serializer = PostSerializer.new(post, user)
|
156
|
+
|
157
|
+
assert_equal({
|
158
|
+
:post => {
|
159
|
+
:title => "New Post",
|
160
|
+
:body => "Body of new post",
|
161
|
+
:comments => [
|
162
|
+
{ :title => "Comment1" },
|
163
|
+
{ :title => "Comment2" }
|
164
|
+
]
|
165
|
+
}
|
166
|
+
}, post_serializer.as_json)
|
167
|
+
end
|
168
|
+
|
169
|
+
class Blog < Model
|
170
|
+
attr_accessor :author
|
171
|
+
end
|
172
|
+
|
173
|
+
class AuthorSerializer < ActiveModel::Serializer
|
174
|
+
attributes :first_name, :last_name
|
175
|
+
end
|
176
|
+
|
177
|
+
class BlogSerializer < ActiveModel::Serializer
|
178
|
+
has_one :author, :serializer => AuthorSerializer
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_has_one
|
182
|
+
user = User.new
|
183
|
+
blog = Blog.new
|
184
|
+
blog.author = user
|
185
|
+
|
186
|
+
json = BlogSerializer.new(blog, user).as_json
|
187
|
+
assert_equal({
|
188
|
+
:blog => {
|
189
|
+
:author => {
|
190
|
+
:first_name => "Jose",
|
191
|
+
:last_name => "Valim"
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}, json)
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_overridden_associations
|
198
|
+
author_serializer = Class.new(ActiveModel::Serializer) do
|
199
|
+
attributes :first_name
|
200
|
+
end
|
201
|
+
|
202
|
+
blog_serializer = Class.new(ActiveModel::Serializer) do
|
203
|
+
def person
|
204
|
+
object.author
|
205
|
+
end
|
206
|
+
|
207
|
+
has_one :person, :serializer => author_serializer
|
208
|
+
end
|
209
|
+
|
210
|
+
user = User.new
|
211
|
+
blog = Blog.new
|
212
|
+
blog.author = user
|
213
|
+
|
214
|
+
json = blog_serializer.new(blog, user).as_json
|
215
|
+
assert_equal({
|
216
|
+
:person => {
|
217
|
+
:first_name => "Jose"
|
218
|
+
}
|
219
|
+
}, json)
|
220
|
+
end
|
221
|
+
|
222
|
+
def post_serializer(type)
|
223
|
+
Class.new(ActiveModel::Serializer) do
|
224
|
+
attributes :title, :body
|
225
|
+
has_many :comments, :serializer => CommentSerializer
|
226
|
+
|
227
|
+
if type != :super
|
228
|
+
define_method :serializable_hash do
|
229
|
+
post_hash = attributes
|
230
|
+
post_hash.merge!(send(type))
|
231
|
+
post_hash
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_associations
|
238
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
|
239
|
+
comments = [Comment.new(:title => "Comment1"), Comment.new(:title => "Comment2")]
|
240
|
+
post.comments = comments
|
241
|
+
|
242
|
+
serializer = post_serializer(:associations).new(post, nil)
|
243
|
+
|
244
|
+
assert_equal({
|
245
|
+
:title => "New Post",
|
246
|
+
:body => "Body of new post",
|
247
|
+
:comments => [
|
248
|
+
{ :title => "Comment1" },
|
249
|
+
{ :title => "Comment2" }
|
250
|
+
]
|
251
|
+
}, serializer.as_json)
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_association_ids
|
255
|
+
serializer = post_serializer(:association_ids)
|
256
|
+
|
257
|
+
serializer.class_eval do
|
258
|
+
def as_json(*)
|
259
|
+
{ :post => serializable_hash }.merge(associations)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
|
264
|
+
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
|
265
|
+
post.comments = comments
|
266
|
+
|
267
|
+
serializer = serializer.new(post, nil)
|
268
|
+
|
269
|
+
assert_equal({
|
270
|
+
:post => {
|
271
|
+
:title => "New Post",
|
272
|
+
:body => "Body of new post",
|
273
|
+
:comments => [1, 2]
|
274
|
+
},
|
275
|
+
:comments => [
|
276
|
+
{ :title => "Comment1" },
|
277
|
+
{ :title => "Comment2" }
|
278
|
+
]
|
279
|
+
}, serializer.as_json)
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_associations_with_nil_association
|
283
|
+
user = User.new
|
284
|
+
blog = Blog.new
|
285
|
+
|
286
|
+
json = BlogSerializer.new(blog, user).as_json
|
287
|
+
assert_equal({
|
288
|
+
:blog => { :author => nil }
|
289
|
+
}, json)
|
290
|
+
|
291
|
+
serializer = Class.new(BlogSerializer) do
|
292
|
+
root :blog
|
293
|
+
|
294
|
+
def serializable_hash
|
295
|
+
attributes.merge(association_ids)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
json = serializer.new(blog, user).as_json
|
300
|
+
assert_equal({ :blog => { :author => nil } }, json)
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_custom_root
|
304
|
+
user = User.new
|
305
|
+
blog = Blog.new
|
306
|
+
|
307
|
+
serializer = Class.new(BlogSerializer) do
|
308
|
+
root :my_blog
|
309
|
+
end
|
310
|
+
|
311
|
+
assert_equal({ :my_blog => { :author => nil } }, serializer.new(blog, user).as_json)
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_false_root
|
315
|
+
user = User.new
|
316
|
+
blog = Blog.new
|
317
|
+
|
318
|
+
serializer = Class.new(BlogSerializer) do
|
319
|
+
root false
|
320
|
+
end
|
321
|
+
|
322
|
+
assert_equal({ :author => nil }, serializer.new(blog, user).as_json)
|
323
|
+
|
324
|
+
# test inherited false root
|
325
|
+
serializer = Class.new(serializer)
|
326
|
+
assert_equal({ :author => nil }, serializer.new(blog, user).as_json)
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_embed_ids
|
330
|
+
serializer = post_serializer(:super)
|
331
|
+
|
332
|
+
serializer.class_eval do
|
333
|
+
root :post
|
334
|
+
embed :ids
|
335
|
+
end
|
336
|
+
|
337
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
|
338
|
+
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
|
339
|
+
post.comments = comments
|
340
|
+
|
341
|
+
serializer = serializer.new(post, nil)
|
342
|
+
|
343
|
+
assert_equal({
|
344
|
+
:post => {
|
345
|
+
:title => "New Post",
|
346
|
+
:body => "Body of new post",
|
347
|
+
:comments => [1, 2]
|
348
|
+
}
|
349
|
+
}, serializer.as_json)
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_embed_ids_include_true
|
353
|
+
serializer = post_serializer(:super)
|
354
|
+
|
355
|
+
serializer.class_eval do
|
356
|
+
root :post
|
357
|
+
embed :ids, :include => true
|
358
|
+
end
|
359
|
+
|
360
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
|
361
|
+
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
|
362
|
+
post.comments = comments
|
363
|
+
|
364
|
+
serializer = serializer.new(post, nil)
|
365
|
+
|
366
|
+
assert_equal({
|
367
|
+
:post => {
|
368
|
+
:title => "New Post",
|
369
|
+
:body => "Body of new post",
|
370
|
+
:comments => [1, 2]
|
371
|
+
},
|
372
|
+
:comments => [
|
373
|
+
{ :title => "Comment1" },
|
374
|
+
{ :title => "Comment2" }
|
375
|
+
]
|
376
|
+
}, serializer.as_json)
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_embed_objects
|
380
|
+
serializer = post_serializer(:super)
|
381
|
+
|
382
|
+
serializer.class_eval do
|
383
|
+
root :post
|
384
|
+
embed :objects
|
385
|
+
end
|
386
|
+
|
387
|
+
post = Post.new(:title => "New Post", :body => "Body of new post", :email => "tenderlove@tenderlove.com")
|
388
|
+
comments = [Comment.new(:title => "Comment1", :id => 1), Comment.new(:title => "Comment2", :id => 2)]
|
389
|
+
post.comments = comments
|
390
|
+
|
391
|
+
serializer = serializer.new(post, nil)
|
392
|
+
|
393
|
+
assert_equal({
|
394
|
+
:post => {
|
395
|
+
:title => "New Post",
|
396
|
+
:body => "Body of new post",
|
397
|
+
:comments => [
|
398
|
+
{ :title => "Comment1" },
|
399
|
+
{ :title => "Comment2" }
|
400
|
+
]
|
401
|
+
}
|
402
|
+
}, serializer.as_json)
|
403
|
+
end
|
404
|
+
|
405
|
+
def test_array_serializer
|
406
|
+
model = Model.new
|
407
|
+
user = User.new
|
408
|
+
comments = Comment.new(:title => "Comment1", :id => 1)
|
409
|
+
|
410
|
+
array = [model, user, comments]
|
411
|
+
serializer = array.active_model_serializer.new(array, {:scope => true})
|
412
|
+
assert_equal([
|
413
|
+
{ :model => "Model" },
|
414
|
+
{ :user => { :last_name=>"Valim", :ok=>true, :first_name=>"Jose", :scope => true } },
|
415
|
+
{ :comment => { :title => "Comment1" } }
|
416
|
+
], serializer.as_json)
|
417
|
+
end
|
418
|
+
|
419
|
+
class CustomBlog < Blog
|
420
|
+
attr_accessor :public_posts, :public_user
|
421
|
+
end
|
422
|
+
|
423
|
+
class CustomBlogSerializer < ActiveModel::Serializer
|
424
|
+
has_many :public_posts, :key => :posts, :serializer => PostSerializer
|
425
|
+
has_one :public_user, :key => :user, :serializer => UserSerializer
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_associations_with_as
|
429
|
+
posts = [
|
430
|
+
Post.new(:title => 'First Post', :body => 'text'),
|
431
|
+
Post.new(:title => 'Second Post', :body => 'text')
|
432
|
+
]
|
433
|
+
user = User.new
|
434
|
+
|
435
|
+
custom_blog = CustomBlog.new
|
436
|
+
custom_blog.public_posts = posts
|
437
|
+
custom_blog.public_user = user
|
438
|
+
|
439
|
+
serializer = CustomBlogSerializer.new(custom_blog, :scope => true)
|
440
|
+
|
441
|
+
assert_equal({
|
442
|
+
:custom_blog => {
|
443
|
+
:posts => [
|
444
|
+
{:title => 'First Post', :body => 'text', :comments => []},
|
445
|
+
{:title => 'Second Post', :body => 'text', :comments => []}
|
446
|
+
],
|
447
|
+
:user => {
|
448
|
+
:first_name => "Jose",
|
449
|
+
:last_name => "Valim", :ok => true,
|
450
|
+
:scope => true
|
451
|
+
}
|
452
|
+
}
|
453
|
+
}, serializer.as_json)
|
454
|
+
end
|
455
|
+
|
456
|
+
def test_implicity_detection_for_association_serializers
|
457
|
+
implicit_serializer = Class.new(ActiveModel::Serializer) do
|
458
|
+
root :custom_blog
|
459
|
+
const_set(:UserSerializer, UserSerializer)
|
460
|
+
const_set(:PostSerializer, PostSerializer)
|
461
|
+
|
462
|
+
has_many :public_posts, :key => :posts
|
463
|
+
has_one :public_user, :key => :user
|
464
|
+
end
|
465
|
+
|
466
|
+
posts = [
|
467
|
+
Post.new(:title => 'First Post', :body => 'text', :comments => []),
|
468
|
+
Post.new(:title => 'Second Post', :body => 'text', :comments => [])
|
469
|
+
]
|
470
|
+
user = User.new
|
471
|
+
|
472
|
+
custom_blog = CustomBlog.new
|
473
|
+
custom_blog.public_posts = posts
|
474
|
+
custom_blog.public_user = user
|
475
|
+
|
476
|
+
serializer = implicit_serializer.new(custom_blog, :scope => true)
|
477
|
+
|
478
|
+
assert_equal({
|
479
|
+
:custom_blog => {
|
480
|
+
:posts => [
|
481
|
+
{:title => 'First Post', :body => 'text', :comments => []},
|
482
|
+
{:title => 'Second Post', :body => 'text', :comments => []}
|
483
|
+
],
|
484
|
+
:user => {
|
485
|
+
:first_name => "Jose",
|
486
|
+
:last_name => "Valim", :ok => true,
|
487
|
+
:scope => true
|
488
|
+
}
|
489
|
+
}
|
490
|
+
}, serializer.as_json)
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_attribute_key
|
494
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
495
|
+
root :user
|
496
|
+
|
497
|
+
attribute :first_name, :key => :firstName
|
498
|
+
attribute :last_name, :key => :lastName
|
499
|
+
attribute :password
|
500
|
+
end
|
501
|
+
|
502
|
+
serializer = serializer_class.new(User.new, nil)
|
503
|
+
|
504
|
+
assert_equal({
|
505
|
+
:user => {
|
506
|
+
:firstName => "Jose",
|
507
|
+
:lastName => "Valim",
|
508
|
+
:password => "oh noes yugive my password"
|
509
|
+
}
|
510
|
+
}, serializer.as_json)
|
511
|
+
end
|
512
|
+
|
513
|
+
def setup_model
|
514
|
+
Class.new do
|
515
|
+
class << self
|
516
|
+
def columns_hash
|
517
|
+
{ "name" => Struct.new(:type).new(:string), "age" => Struct.new(:type).new(:integer) }
|
518
|
+
end
|
519
|
+
|
520
|
+
def reflect_on_association(name)
|
521
|
+
case name
|
522
|
+
when :posts
|
523
|
+
Struct.new(:macro, :name).new(:has_many, :posts)
|
524
|
+
when :parent
|
525
|
+
Struct.new(:macro, :name).new(:belongs_to, :parent)
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
def test_schema
|
533
|
+
model = setup_model
|
534
|
+
|
535
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
536
|
+
class << self; self; end.class_eval do
|
537
|
+
define_method(:model_class) do model end
|
538
|
+
end
|
539
|
+
|
540
|
+
attributes :name, :age
|
541
|
+
has_many :posts, :serializer => Class.new
|
542
|
+
has_one :parent, :serializer => Class.new
|
543
|
+
end
|
544
|
+
|
545
|
+
assert_equal serializer.schema, {
|
546
|
+
:attributes => { :name => :string, :age => :integer },
|
547
|
+
:associations => {
|
548
|
+
:posts => { :has_many => :posts },
|
549
|
+
:parent => { :belongs_to => :parent }
|
550
|
+
}
|
551
|
+
}
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_schema_with_as
|
555
|
+
model = setup_model
|
556
|
+
|
557
|
+
serializer = Class.new(ActiveModel::Serializer) do
|
558
|
+
class << self; self; end.class_eval do
|
559
|
+
define_method(:model_class) do model end
|
560
|
+
end
|
561
|
+
|
562
|
+
attributes :name, :age
|
563
|
+
has_many :posts, :key => :my_posts, :serializer => Class.new
|
564
|
+
has_one :parent, :key => :my_parent, :serializer => Class.new
|
565
|
+
end
|
566
|
+
|
567
|
+
assert_equal serializer.schema, {
|
568
|
+
:attributes => { :name => :string, :age => :integer },
|
569
|
+
:associations => {
|
570
|
+
:my_posts => { :has_many => :posts },
|
571
|
+
:my_parent => { :belongs_to => :parent }
|
572
|
+
}
|
573
|
+
}
|
574
|
+
end
|
575
|
+
|
576
|
+
def test_embed_id_for_has_one
|
577
|
+
author_serializer = Class.new(ActiveModel::Serializer)
|
578
|
+
|
579
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
580
|
+
embed :ids
|
581
|
+
root :post
|
582
|
+
|
583
|
+
attributes :title, :body
|
584
|
+
has_one :author, :serializer => author_serializer
|
585
|
+
end
|
586
|
+
|
587
|
+
post_class = Class.new(Model) do
|
588
|
+
attr_accessor :author
|
589
|
+
end
|
590
|
+
|
591
|
+
author_class = Class.new(Model)
|
592
|
+
|
593
|
+
post = post_class.new(:title => "New Post", :body => "It's a new post!")
|
594
|
+
author = author_class.new(:id => 5)
|
595
|
+
post.author = author
|
596
|
+
|
597
|
+
hash = serializer_class.new(post, nil)
|
598
|
+
|
599
|
+
assert_equal({
|
600
|
+
:post => {
|
601
|
+
:title => "New Post",
|
602
|
+
:body => "It's a new post!",
|
603
|
+
:author => 5
|
604
|
+
}
|
605
|
+
}, hash.as_json)
|
606
|
+
end
|
607
|
+
|
608
|
+
def test_embed_objects_for_has_one
|
609
|
+
author_serializer = Class.new(ActiveModel::Serializer) do
|
610
|
+
attributes :id, :name
|
611
|
+
end
|
612
|
+
|
613
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
614
|
+
root :post
|
615
|
+
|
616
|
+
attributes :title, :body
|
617
|
+
has_one :author, :serializer => author_serializer
|
618
|
+
end
|
619
|
+
|
620
|
+
post_class = Class.new(Model) do
|
621
|
+
attr_accessor :author
|
622
|
+
end
|
623
|
+
|
624
|
+
author_class = Class.new(Model)
|
625
|
+
|
626
|
+
post = post_class.new(:title => "New Post", :body => "It's a new post!")
|
627
|
+
author = author_class.new(:id => 5, :name => "Tom Dale")
|
628
|
+
post.author = author
|
629
|
+
|
630
|
+
hash = serializer_class.new(post, nil)
|
631
|
+
|
632
|
+
assert_equal({
|
633
|
+
:post => {
|
634
|
+
:title => "New Post",
|
635
|
+
:body => "It's a new post!",
|
636
|
+
:author => { :id => 5, :name => "Tom Dale" }
|
637
|
+
}
|
638
|
+
}, hash.as_json)
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_root_provided_in_options
|
642
|
+
author_serializer = Class.new(ActiveModel::Serializer) do
|
643
|
+
attributes :id, :name
|
644
|
+
end
|
645
|
+
|
646
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
647
|
+
root :post
|
648
|
+
|
649
|
+
attributes :title, :body
|
650
|
+
has_one :author, :serializer => author_serializer
|
651
|
+
end
|
652
|
+
|
653
|
+
post_class = Class.new(Model) do
|
654
|
+
attr_accessor :author
|
655
|
+
end
|
656
|
+
|
657
|
+
author_class = Class.new(Model)
|
658
|
+
|
659
|
+
post = post_class.new(:title => "New Post", :body => "It's a new post!")
|
660
|
+
author = author_class.new(:id => 5, :name => "Tom Dale")
|
661
|
+
post.author = author
|
662
|
+
|
663
|
+
assert_equal({
|
664
|
+
:blog_post => {
|
665
|
+
:title => "New Post",
|
666
|
+
:body => "It's a new post!",
|
667
|
+
:author => { :id => 5, :name => "Tom Dale" }
|
668
|
+
}
|
669
|
+
}, serializer_class.new(post, nil, :root => :blog_post).as_json)
|
670
|
+
|
671
|
+
assert_equal({
|
672
|
+
:title => "New Post",
|
673
|
+
:body => "It's a new post!",
|
674
|
+
:author => { :id => 5, :name => "Tom Dale" }
|
675
|
+
}, serializer_class.new(post, nil, :root => false).as_json)
|
676
|
+
|
677
|
+
assert_equal({
|
678
|
+
:blog_post => {
|
679
|
+
:title => "New Post",
|
680
|
+
:body => "It's a new post!",
|
681
|
+
:author => { :id => 5, :name => "Tom Dale" }
|
682
|
+
}
|
683
|
+
}, serializer_class.new(post, nil).as_json(:root => :blog_post))
|
684
|
+
|
685
|
+
assert_equal({
|
686
|
+
:title => "New Post",
|
687
|
+
:body => "It's a new post!",
|
688
|
+
:author => { :id => 5, :name => "Tom Dale" }
|
689
|
+
}, serializer_class.new(post, nil).as_json(:root => false))
|
690
|
+
end
|
691
|
+
|
692
|
+
def test_serializer_has_access_to_root_object
|
693
|
+
hash_object = nil
|
694
|
+
|
695
|
+
author_serializer = Class.new(ActiveModel::Serializer) do
|
696
|
+
attributes :id, :name
|
697
|
+
|
698
|
+
define_method :serializable_hash do
|
699
|
+
hash_object = @hash
|
700
|
+
super()
|
701
|
+
end
|
702
|
+
end
|
703
|
+
|
704
|
+
serializer_class = Class.new(ActiveModel::Serializer) do
|
705
|
+
root :post
|
706
|
+
|
707
|
+
attributes :title, :body
|
708
|
+
has_one :author, :serializer => author_serializer
|
709
|
+
end
|
710
|
+
|
711
|
+
post_class = Class.new(Model) do
|
712
|
+
attr_accessor :author
|
713
|
+
end
|
714
|
+
|
715
|
+
author_class = Class.new(Model)
|
716
|
+
|
717
|
+
post = post_class.new(:title => "New Post", :body => "It's a new post!")
|
718
|
+
author = author_class.new(:id => 5, :name => "Tom Dale")
|
719
|
+
post.author = author
|
720
|
+
|
721
|
+
expected = serializer_class.new(post, nil).as_json
|
722
|
+
assert_equal expected, hash_object
|
723
|
+
end
|
724
|
+
|
725
|
+
# the point of this test is to illustrate that deeply nested serializers
|
726
|
+
# still side-load at the root.
|
727
|
+
def test_embed_with_include_inserts_at_root
|
728
|
+
tag_serializer = Class.new(ActiveModel::Serializer) do
|
729
|
+
attributes :id, :name
|
730
|
+
end
|
731
|
+
|
732
|
+
comment_serializer = Class.new(ActiveModel::Serializer) do
|
733
|
+
embed :ids, :include => true
|
734
|
+
attributes :id, :body
|
735
|
+
has_many :tags, :serializer => tag_serializer
|
736
|
+
end
|
737
|
+
|
738
|
+
post_serializer = Class.new(ActiveModel::Serializer) do
|
739
|
+
embed :ids, :include => true
|
740
|
+
attributes :id, :title, :body
|
741
|
+
has_many :comments, :serializer => comment_serializer
|
742
|
+
end
|
743
|
+
|
744
|
+
post_class = Class.new(Model) do
|
745
|
+
attr_accessor :comments
|
746
|
+
|
747
|
+
define_method :active_model_serializer do
|
748
|
+
post_serializer
|
749
|
+
end
|
750
|
+
end
|
751
|
+
|
752
|
+
comment_class = Class.new(Model) do
|
753
|
+
attr_accessor :tags
|
754
|
+
end
|
755
|
+
|
756
|
+
tag_class = Class.new(Model)
|
757
|
+
|
758
|
+
post = post_class.new(:title => "New Post", :body => "NEW POST", :id => 1)
|
759
|
+
comment1 = comment_class.new(:body => "EWOT", :id => 1)
|
760
|
+
comment2 = comment_class.new(:body => "YARLY", :id => 2)
|
761
|
+
tag1 = tag_class.new(:name => "lolcat", :id => 1)
|
762
|
+
tag2 = tag_class.new(:name => "nyancat", :id => 2)
|
763
|
+
tag3 = tag_class.new(:name => "violetcat", :id => 3)
|
764
|
+
|
765
|
+
post.comments = [comment1, comment2]
|
766
|
+
comment1.tags = [tag1, tag3]
|
767
|
+
comment2.tags = [tag1, tag2]
|
768
|
+
|
769
|
+
actual = ActiveModel::ArraySerializer.new([post], nil, :root => :posts).as_json
|
770
|
+
assert_equal({
|
771
|
+
:posts => [
|
772
|
+
{ :title => "New Post", :body => "NEW POST", :id => 1, :comments => [1,2] }
|
773
|
+
],
|
774
|
+
|
775
|
+
:comments => [
|
776
|
+
{ :body => "EWOT", :id => 1, :tags => [1,3] },
|
777
|
+
{ :body => "YARLY", :id => 2, :tags => [1,2] }
|
778
|
+
],
|
779
|
+
|
780
|
+
:tags => [
|
781
|
+
{ :name => "lolcat", :id => 1 },
|
782
|
+
{ :name => "violetcat", :id => 3 },
|
783
|
+
{ :name => "nyancat", :id => 2 }
|
784
|
+
]
|
785
|
+
}, actual)
|
786
|
+
end
|
787
|
+
end
|