active_model_serializers 0.10.0 → 0.10.7
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.
- checksums.yaml +5 -5
- data/.rubocop.yml +6 -5
- data/.travis.yml +30 -21
- data/CHANGELOG.md +172 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +23 -4
- data/README.md +166 -28
- data/Rakefile +3 -32
- data/active_model_serializers.gemspec +22 -25
- data/appveyor.yml +10 -6
- data/bin/rubocop +38 -0
- data/docs/README.md +2 -1
- data/docs/general/adapters.md +35 -11
- data/docs/general/caching.md +7 -1
- data/docs/general/configuration_options.md +86 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +1 -1
- data/docs/general/logging.md +7 -0
- data/docs/general/rendering.md +63 -25
- data/docs/general/serializers.md +125 -14
- data/docs/howto/add_pagination_links.md +16 -17
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +11 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +12 -4
- data/docs/howto/passing_arbitrary_options.md +2 -2
- data/docs/howto/serialize_poro.md +46 -5
- data/docs/howto/test.md +2 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +67 -32
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +13 -3
- data/lib/active_model/serializer/adapter/base.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +8 -5
- data/lib/active_model/serializer/association.rb +62 -10
- data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
- data/lib/active_model/serializer/collection_serializer.rb +39 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
- data/lib/active_model/serializer/error_serializer.rb +11 -7
- data/lib/active_model/serializer/errors_serializer.rb +25 -20
- data/lib/active_model/serializer/has_many_reflection.rb +3 -3
- data/lib/active_model/serializer/has_one_reflection.rb +1 -4
- data/lib/active_model/serializer/lazy_association.rb +95 -0
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +127 -67
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +297 -79
- data/lib/active_model_serializers/adapter/attributes.rb +3 -66
- data/lib/active_model_serializers/adapter/base.rb +39 -39
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +47 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
- data/lib/active_model_serializers/adapter/json_api.rb +71 -57
- data/lib/active_model_serializers/adapter.rb +6 -0
- data/lib/active_model_serializers/deprecate.rb +1 -2
- data/lib/active_model_serializers/deserialization.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +80 -0
- data/lib/active_model_serializers/model.rb +109 -28
- data/lib/active_model_serializers/railtie.rb +3 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
- data/lib/active_model_serializers/serializable_resource.rb +6 -5
- data/lib/active_model_serializers/serialization_context.rb +10 -3
- data/lib/active_model_serializers/test/schema.rb +2 -2
- data/lib/active_model_serializers.rb +16 -1
- data/lib/generators/rails/resource_override.rb +1 -1
- data/lib/generators/rails/serializer_generator.rb +4 -4
- data/lib/grape/active_model_serializers.rb +7 -5
- data/lib/grape/formatters/active_model_serializers.rb +19 -2
- data/lib/grape/helpers/active_model_serializers.rb +1 -0
- data/lib/tasks/rubocop.rake +53 -0
- data/test/action_controller/adapter_selector_test.rb +14 -5
- data/test/action_controller/explicit_serializer_test.rb +5 -4
- data/test/action_controller/json/include_test.rb +106 -27
- data/test/action_controller/json_api/deserialization_test.rb +1 -1
- data/test/action_controller/json_api/errors_test.rb +8 -9
- data/test/action_controller/json_api/fields_test.rb +66 -0
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +31 -23
- data/test/action_controller/json_api/transform_test.rb +11 -3
- data/test/action_controller/lookup_proc_test.rb +49 -0
- data/test/action_controller/namespace_lookup_test.rb +232 -0
- data/test/action_controller/serialization_scope_name_test.rb +12 -6
- data/test/action_controller/serialization_test.rb +12 -9
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/model_test.rb +137 -4
- data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/active_model_serializers/test/schema_test.rb +3 -2
- data/test/adapter/attributes_test.rb +40 -0
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/has_many_test.rb +10 -2
- data/test/adapter/json/transform_test.rb +15 -15
- data/test/adapter/json_api/collection_test.rb +4 -3
- data/test/adapter/json_api/errors_test.rb +17 -19
- data/test/adapter/json_api/fields_test.rb +12 -3
- data/test/adapter/json_api/has_many_test.rb +49 -20
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -0
- data/test/adapter/json_api/json_api_test.rb +5 -7
- data/test/adapter/json_api/linked_test.rb +33 -12
- data/test/adapter/json_api/links_test.rb +4 -2
- data/test/adapter/json_api/pagination_links_test.rb +53 -13
- data/test/adapter/json_api/parse_test.rb +1 -1
- data/test/adapter/json_api/relationship_test.rb +309 -73
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +263 -253
- data/test/adapter/json_api/type_test.rb +168 -36
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +52 -5
- data/test/adapter_test.rb +1 -1
- data/test/benchmark/app.rb +1 -1
- data/test/benchmark/benchmarking_support.rb +1 -1
- data/test/benchmark/bm_active_record.rb +81 -0
- data/test/benchmark/bm_adapter.rb +38 -0
- data/test/benchmark/bm_caching.rb +16 -16
- data/test/benchmark/bm_lookup_chain.rb +83 -0
- data/test/benchmark/bm_transform.rb +21 -10
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +235 -69
- data/test/collection_serializer_test.rb +31 -14
- data/test/fixtures/active_record.rb +45 -10
- data/test/fixtures/poro.rb +124 -181
- data/test/generators/serializer_generator_test.rb +23 -5
- data/test/grape_test.rb +170 -56
- data/test/lint_test.rb +1 -1
- data/test/logger_test.rb +13 -11
- data/test/serializable_resource_test.rb +18 -22
- data/test/serializers/association_macros_test.rb +3 -2
- data/test/serializers/associations_test.rb +222 -49
- data/test/serializers/attribute_test.rb +5 -3
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/caching_configuration_test_isolated.rb +6 -6
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/options_test.rb +17 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
- data/test/serializers/reflection_test.rb +427 -0
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serialization_test.rb +2 -2
- data/test/serializers/serializer_for_test.rb +12 -10
- data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
- data/test/support/isolated_unit.rb +9 -4
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +2 -9
- data/test/support/serialization_testing.rb +31 -5
- data/test/test_helper.rb +13 -0
- metadata +130 -71
- data/.rubocop_todo.yml +0 -167
- data/docs/ARCHITECTURE.md +0 -126
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
data/test/fixtures/poro.rb
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
verbose = $VERBOSE
|
|
2
|
-
$VERBOSE = nil
|
|
3
1
|
class Model < ActiveModelSerializers::Model
|
|
4
|
-
|
|
2
|
+
rand(2).zero? && derive_attributes_from_names_and_fix_accessors
|
|
5
3
|
|
|
6
|
-
|
|
4
|
+
attr_writer :id
|
|
7
5
|
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
# At this time, just for organization of intent
|
|
7
|
+
class_attribute :association_names
|
|
8
|
+
self.association_names = []
|
|
9
|
+
|
|
10
|
+
def self.associations(*names)
|
|
11
|
+
self.association_names |= names.map(&:to_sym)
|
|
12
|
+
# Silence redefinition of methods warnings
|
|
13
|
+
ActiveModelSerializers.silence_warnings do
|
|
14
|
+
attr_accessor(*names)
|
|
16
15
|
end
|
|
17
16
|
end
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
def associations
|
|
19
|
+
association_names.each_with_object({}) do |association_name, result|
|
|
20
|
+
result[association_name] = public_send(association_name).freeze
|
|
21
|
+
end.with_indifferent_access.freeze
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def attributes
|
|
25
|
+
super.except(*association_names)
|
|
23
26
|
end
|
|
24
27
|
end
|
|
25
28
|
|
|
@@ -30,67 +33,60 @@ end
|
|
|
30
33
|
# model = ModelWithErrors.new
|
|
31
34
|
# model.validate! # => ["cannot be nil"]
|
|
32
35
|
# model.errors.full_messages # => ["name cannot be nil"]
|
|
33
|
-
class ModelWithErrors <
|
|
34
|
-
|
|
36
|
+
class ModelWithErrors < Model
|
|
37
|
+
attributes :name
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
class Profile < Model
|
|
41
|
+
attributes :name, :description
|
|
42
|
+
associations :comments
|
|
38
43
|
end
|
|
39
|
-
|
|
40
44
|
class ProfileSerializer < ActiveModel::Serializer
|
|
41
45
|
attributes :name, :description
|
|
42
|
-
|
|
43
|
-
# TODO: is this used anywhere?
|
|
44
|
-
def arguments_passed_in?
|
|
45
|
-
instance_options[:my_options] == :accessible
|
|
46
|
-
end
|
|
47
46
|
end
|
|
48
|
-
|
|
49
47
|
class ProfilePreviewSerializer < ActiveModel::Serializer
|
|
50
48
|
attributes :name
|
|
51
49
|
end
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Bio = Class.new(Model)
|
|
57
|
-
Blog = Class.new(Model)
|
|
58
|
-
Role = Class.new(Model)
|
|
59
|
-
User = Class.new(Model)
|
|
60
|
-
Location = Class.new(Model)
|
|
61
|
-
Place = Class.new(Model)
|
|
62
|
-
Tag = Class.new(Model)
|
|
63
|
-
VirtualValue = Class.new(Model)
|
|
64
|
-
Comment = Class.new(Model) do
|
|
65
|
-
# Uses a custom non-time-based cache key
|
|
66
|
-
def cache_key
|
|
67
|
-
"#{self.class.name.downcase}/#{self.id}"
|
|
68
|
-
end
|
|
51
|
+
class Author < Model
|
|
52
|
+
attributes :name
|
|
53
|
+
associations :posts, :bio, :roles, :comments
|
|
69
54
|
end
|
|
55
|
+
class AuthorSerializer < ActiveModel::Serializer
|
|
56
|
+
cache key: 'writer', skip_digest: true
|
|
57
|
+
attribute :id
|
|
58
|
+
attribute :name
|
|
70
59
|
|
|
71
|
-
|
|
72
|
-
has_many :
|
|
73
|
-
|
|
60
|
+
has_many :posts
|
|
61
|
+
has_many :roles
|
|
62
|
+
has_one :bio
|
|
74
63
|
end
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
belongs_to :taggable, polymorphic: true
|
|
64
|
+
class AuthorPreviewSerializer < ActiveModel::Serializer
|
|
65
|
+
attributes :id
|
|
66
|
+
has_many :posts
|
|
79
67
|
end
|
|
80
68
|
|
|
81
|
-
class
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
class Comment < Model
|
|
70
|
+
attributes :body, :date
|
|
71
|
+
associations :post, :author, :likes
|
|
84
72
|
end
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
73
|
+
class CommentSerializer < ActiveModel::Serializer
|
|
74
|
+
cache expires_in: 1.day, skip_digest: true
|
|
75
|
+
attributes :id, :body
|
|
76
|
+
belongs_to :post
|
|
77
|
+
belongs_to :author
|
|
88
78
|
end
|
|
79
|
+
class CommentPreviewSerializer < ActiveModel::Serializer
|
|
80
|
+
attributes :id
|
|
89
81
|
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
belongs_to :post
|
|
83
|
+
end
|
|
92
84
|
|
|
93
|
-
|
|
85
|
+
class Post < Model
|
|
86
|
+
attributes :title, :body
|
|
87
|
+
associations :author, :comments, :blog, :tags, :related
|
|
88
|
+
end
|
|
89
|
+
class PostSerializer < ActiveModel::Serializer
|
|
94
90
|
cache key: 'post', expires_in: 0.1, skip_digest: true
|
|
95
91
|
attributes :id, :title, :body
|
|
96
92
|
|
|
@@ -101,143 +97,116 @@ PostSerializer = Class.new(ActiveModel::Serializer) do
|
|
|
101
97
|
def blog
|
|
102
98
|
Blog.new(id: 999, name: 'Custom blog')
|
|
103
99
|
end
|
|
104
|
-
|
|
105
|
-
# TODO: is this used anywhere?
|
|
106
|
-
def custom_options
|
|
107
|
-
instance_options
|
|
108
|
-
end
|
|
109
100
|
end
|
|
110
|
-
|
|
111
|
-
SpammyPostSerializer = Class.new(ActiveModel::Serializer) do
|
|
101
|
+
class SpammyPostSerializer < ActiveModel::Serializer
|
|
112
102
|
attributes :id
|
|
113
103
|
has_many :related
|
|
114
104
|
end
|
|
105
|
+
class PostPreviewSerializer < ActiveModel::Serializer
|
|
106
|
+
attributes :title, :body, :id
|
|
115
107
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
attributes :id, :body
|
|
119
|
-
|
|
120
|
-
belongs_to :post
|
|
121
|
-
belongs_to :author
|
|
122
|
-
|
|
123
|
-
def custom_options
|
|
124
|
-
instance_options
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
AuthorSerializer = Class.new(ActiveModel::Serializer) do
|
|
129
|
-
cache key: 'writer', skip_digest: true
|
|
130
|
-
attribute :id
|
|
131
|
-
attribute :name
|
|
132
|
-
|
|
133
|
-
has_many :posts
|
|
134
|
-
has_many :roles
|
|
135
|
-
has_one :bio
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
RoleSerializer = Class.new(ActiveModel::Serializer) do
|
|
139
|
-
cache only: [:name], skip_digest: true
|
|
140
|
-
attributes :id, :name, :description, :slug
|
|
141
|
-
|
|
142
|
-
def slug
|
|
143
|
-
"#{object.name}-#{object.id}"
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
belongs_to :author
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
LikeSerializer = Class.new(ActiveModel::Serializer) do
|
|
150
|
-
attributes :id, :time
|
|
151
|
-
|
|
152
|
-
belongs_to :likeable
|
|
108
|
+
has_many :comments, serializer: ::CommentPreviewSerializer
|
|
109
|
+
belongs_to :author, serializer: ::AuthorPreviewSerializer
|
|
153
110
|
end
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
belongs_to :place
|
|
160
|
-
|
|
161
|
-
def place
|
|
162
|
-
'Nowhere'
|
|
163
|
-
end
|
|
111
|
+
class PostWithCustomKeysSerializer < ActiveModel::Serializer
|
|
112
|
+
attributes :id
|
|
113
|
+
has_many :comments, key: :reviews
|
|
114
|
+
belongs_to :author, key: :writer
|
|
115
|
+
has_one :blog, key: :site
|
|
164
116
|
end
|
|
165
117
|
|
|
166
|
-
|
|
167
|
-
attributes :
|
|
168
|
-
|
|
169
|
-
has_many :locations
|
|
118
|
+
class Bio < Model
|
|
119
|
+
attributes :content, :rating
|
|
120
|
+
associations :author
|
|
170
121
|
end
|
|
171
|
-
|
|
172
|
-
BioSerializer = Class.new(ActiveModel::Serializer) do
|
|
122
|
+
class BioSerializer < ActiveModel::Serializer
|
|
173
123
|
cache except: [:content], skip_digest: true
|
|
174
124
|
attributes :id, :content, :rating
|
|
175
125
|
|
|
176
126
|
belongs_to :author
|
|
177
127
|
end
|
|
178
128
|
|
|
179
|
-
|
|
129
|
+
class Blog < Model
|
|
130
|
+
attributes :name, :type, :special_attribute
|
|
131
|
+
associations :writer, :articles
|
|
132
|
+
end
|
|
133
|
+
class BlogSerializer < ActiveModel::Serializer
|
|
180
134
|
cache key: 'blog'
|
|
181
135
|
attributes :id, :name
|
|
182
136
|
|
|
183
137
|
belongs_to :writer
|
|
184
138
|
has_many :articles
|
|
185
139
|
end
|
|
186
|
-
|
|
187
|
-
PaginatedSerializer = Class.new(ActiveModel::Serializer::CollectionSerializer) do
|
|
188
|
-
def json_key
|
|
189
|
-
'paginated'
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
AlternateBlogSerializer = Class.new(ActiveModel::Serializer) do
|
|
140
|
+
class AlternateBlogSerializer < ActiveModel::Serializer
|
|
194
141
|
attribute :id
|
|
195
142
|
attribute :name, key: :title
|
|
196
143
|
end
|
|
197
|
-
|
|
198
|
-
CustomBlogSerializer = Class.new(ActiveModel::Serializer) do
|
|
144
|
+
class CustomBlogSerializer < ActiveModel::Serializer
|
|
199
145
|
attribute :id
|
|
200
146
|
attribute :special_attribute
|
|
201
|
-
|
|
202
147
|
has_many :articles
|
|
203
148
|
end
|
|
204
149
|
|
|
205
|
-
|
|
206
|
-
attributes :
|
|
207
|
-
|
|
208
|
-
belongs_to :post
|
|
150
|
+
class Role < Model
|
|
151
|
+
attributes :name, :description, :special_attribute
|
|
152
|
+
associations :author
|
|
209
153
|
end
|
|
154
|
+
class RoleSerializer < ActiveModel::Serializer
|
|
155
|
+
cache only: [:name, :slug], skip_digest: true
|
|
156
|
+
attributes :id, :name, :description
|
|
157
|
+
attribute :friendly_id, key: :slug
|
|
158
|
+
belongs_to :author
|
|
210
159
|
|
|
211
|
-
|
|
212
|
-
|
|
160
|
+
def friendly_id
|
|
161
|
+
"#{object.name}-#{object.id}"
|
|
162
|
+
end
|
|
163
|
+
end
|
|
213
164
|
|
|
214
|
-
|
|
165
|
+
class Location < Model
|
|
166
|
+
attributes :lat, :lng
|
|
167
|
+
associations :place
|
|
215
168
|
end
|
|
169
|
+
class LocationSerializer < ActiveModel::Serializer
|
|
170
|
+
cache only: [:address], skip_digest: true
|
|
171
|
+
attributes :id, :lat, :lng
|
|
216
172
|
|
|
217
|
-
|
|
218
|
-
attributes :title, :body, :id
|
|
173
|
+
belongs_to :place, key: :address
|
|
219
174
|
|
|
220
|
-
|
|
221
|
-
|
|
175
|
+
def place
|
|
176
|
+
'Nowhere'
|
|
177
|
+
end
|
|
222
178
|
end
|
|
223
179
|
|
|
224
|
-
|
|
225
|
-
attributes :
|
|
226
|
-
|
|
227
|
-
|
|
180
|
+
class Place < Model
|
|
181
|
+
attributes :name
|
|
182
|
+
associations :locations
|
|
183
|
+
end
|
|
184
|
+
class PlaceSerializer < ActiveModel::Serializer
|
|
185
|
+
attributes :id, :name
|
|
186
|
+
has_many :locations
|
|
228
187
|
end
|
|
229
188
|
|
|
230
|
-
|
|
231
|
-
attributes :
|
|
189
|
+
class Like < Model
|
|
190
|
+
attributes :time
|
|
191
|
+
associations :likeable
|
|
192
|
+
end
|
|
193
|
+
class LikeSerializer < ActiveModel::Serializer
|
|
194
|
+
attributes :id, :time
|
|
195
|
+
belongs_to :likeable
|
|
196
|
+
end
|
|
232
197
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
198
|
+
module Spam
|
|
199
|
+
class UnrelatedLink < Model
|
|
200
|
+
end
|
|
201
|
+
class UnrelatedLinkSerializer < ActiveModel::Serializer
|
|
202
|
+
cache only: [:id]
|
|
203
|
+
attributes :id
|
|
204
|
+
end
|
|
236
205
|
end
|
|
237
206
|
|
|
238
|
-
|
|
207
|
+
class VirtualValue < Model; end
|
|
208
|
+
class VirtualValueSerializer < ActiveModel::Serializer
|
|
239
209
|
attributes :id
|
|
240
|
-
|
|
241
210
|
has_many :reviews, virtual_value: [{ type: 'reviews', id: '1' },
|
|
242
211
|
{ type: 'reviews', id: '2' }]
|
|
243
212
|
has_one :maker, virtual_value: { type: 'makers', id: '1' }
|
|
@@ -249,34 +218,8 @@ VirtualValueSerializer = Class.new(ActiveModel::Serializer) do
|
|
|
249
218
|
end
|
|
250
219
|
end
|
|
251
220
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
PolymorphicBelongsToSerializer = Class.new(ActiveModel::Serializer) do
|
|
257
|
-
attributes :id, :title
|
|
258
|
-
|
|
259
|
-
has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
PolymorphicSimpleSerializer = Class.new(ActiveModel::Serializer) do
|
|
263
|
-
attributes :id
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
PolymorphicObjectTagSerializer = Class.new(ActiveModel::Serializer) do
|
|
267
|
-
attributes :id
|
|
268
|
-
|
|
269
|
-
has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
PolymorphicTagSerializer = Class.new(ActiveModel::Serializer) do
|
|
273
|
-
attributes :id, :phrase
|
|
274
|
-
|
|
275
|
-
has_many :object_tags, serializer: PolymorphicObjectTagSerializer
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do
|
|
279
|
-
cache only: [:id]
|
|
280
|
-
attributes :id
|
|
221
|
+
class PaginatedSerializer < ActiveModel::Serializer::CollectionSerializer
|
|
222
|
+
def json_key
|
|
223
|
+
'paginated'
|
|
224
|
+
end
|
|
281
225
|
end
|
|
282
|
-
$VERBOSE = verbose
|
|
@@ -20,11 +20,10 @@ class SerializerGeneratorTest < Rails::Generators::TestCase
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def test_uses_application_serializer_if_one_exists
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Object.send :remove_const, :ApplicationSerializer
|
|
23
|
+
stub_safe_constantize(expected: 'ApplicationSerializer') do
|
|
24
|
+
run_generator
|
|
25
|
+
assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ApplicationSerializer/
|
|
26
|
+
end
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def test_uses_given_parent
|
|
@@ -54,4 +53,23 @@ class SerializerGeneratorTest < Rails::Generators::TestCase
|
|
|
54
53
|
end
|
|
55
54
|
end
|
|
56
55
|
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def stub_safe_constantize(expected:)
|
|
60
|
+
String.class_eval do
|
|
61
|
+
alias_method :old, :safe_constantize
|
|
62
|
+
end
|
|
63
|
+
String.send(:define_method, :safe_constantize) do
|
|
64
|
+
Class if self == expected
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
yield
|
|
68
|
+
ensure
|
|
69
|
+
String.class_eval do
|
|
70
|
+
undef_method :safe_constantize
|
|
71
|
+
alias_method :safe_constantize, :old
|
|
72
|
+
undef_method :old
|
|
73
|
+
end
|
|
74
|
+
end
|
|
57
75
|
end
|
data/test/grape_test.rb
CHANGED
|
@@ -1,82 +1,196 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
|
-
|
|
2
|
+
TestHelper.silence_warnings do
|
|
3
|
+
require 'grape'
|
|
4
|
+
end
|
|
3
5
|
require 'grape/active_model_serializers'
|
|
6
|
+
require 'kaminari'
|
|
7
|
+
require 'kaminari/hooks'
|
|
8
|
+
::Kaminari::Hooks.init
|
|
9
|
+
|
|
10
|
+
module ActiveModelSerializers
|
|
11
|
+
class GrapeTest < ActiveSupport::TestCase
|
|
12
|
+
include Rack::Test::Methods
|
|
13
|
+
module Models
|
|
14
|
+
def self.model1
|
|
15
|
+
ARModels::Post.new(id: 1, title: 'Dummy Title', body: 'Lorem Ipsum')
|
|
16
|
+
end
|
|
4
17
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def self.model1
|
|
9
|
-
ARModels::Post.new(id: 1, title: 'Dummy Title', body: 'Lorem Ipsum')
|
|
10
|
-
end
|
|
18
|
+
def self.model2
|
|
19
|
+
ARModels::Post.new(id: 2, title: 'Second Dummy Title', body: 'Second Lorem Ipsum')
|
|
20
|
+
end
|
|
11
21
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
def self.all
|
|
23
|
+
@all ||=
|
|
24
|
+
begin
|
|
25
|
+
model1.save!
|
|
26
|
+
model2.save!
|
|
27
|
+
ARModels::Post.all
|
|
28
|
+
end
|
|
29
|
+
end
|
|
15
30
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
def self.reset_all
|
|
32
|
+
ARModels::Post.delete_all
|
|
33
|
+
@all = nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.collection_per
|
|
37
|
+
2
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.collection
|
|
41
|
+
@collection ||=
|
|
42
|
+
begin
|
|
43
|
+
Kaminari.paginate_array(
|
|
44
|
+
[
|
|
45
|
+
Profile.new(id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
|
|
46
|
+
Profile.new(id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
|
|
47
|
+
Profile.new(id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3'),
|
|
48
|
+
Profile.new(id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4'),
|
|
49
|
+
Profile.new(id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5')
|
|
50
|
+
]
|
|
51
|
+
).page(1).per(collection_per)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
23
54
|
end
|
|
24
|
-
end
|
|
25
55
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
56
|
+
class GrapeTest < Grape::API
|
|
57
|
+
format :json
|
|
58
|
+
TestHelper.silence_warnings do
|
|
59
|
+
include Grape::ActiveModelSerializers
|
|
60
|
+
end
|
|
29
61
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
62
|
+
def self.resources(*)
|
|
63
|
+
TestHelper.silence_warnings do
|
|
64
|
+
super
|
|
65
|
+
end
|
|
33
66
|
end
|
|
34
67
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
68
|
+
resources :grape do
|
|
69
|
+
get '/render' do
|
|
70
|
+
render Models.model1
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
get '/render_with_json_api' do
|
|
74
|
+
post = Models.model1
|
|
75
|
+
render post, meta: { page: 1, total_pages: 2 }, adapter: :json_api
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
get '/render_array_with_json_api' do
|
|
79
|
+
posts = Models.all
|
|
80
|
+
render posts, adapter: :json_api
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
get '/render_collection_with_json_api' do
|
|
84
|
+
posts = Models.collection
|
|
85
|
+
render posts, adapter: :json_api
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
get '/render_with_implicit_formatter' do
|
|
89
|
+
Models.model1
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
get '/render_array_with_implicit_formatter' do
|
|
93
|
+
Models.all
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
get '/render_collection_with_implicit_formatter' do
|
|
97
|
+
Models.collection
|
|
98
|
+
end
|
|
38
99
|
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def app
|
|
103
|
+
Grape::Middleware::Globals.new(GrapeTest.new)
|
|
104
|
+
end
|
|
39
105
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
106
|
+
extend Minitest::Assertions
|
|
107
|
+
def self.run_one_method(*)
|
|
108
|
+
_, stderr = capture_io do
|
|
109
|
+
super
|
|
43
110
|
end
|
|
111
|
+
fail Minitest::Assertion, stderr if stderr !~ /grape/
|
|
44
112
|
end
|
|
45
|
-
end
|
|
46
113
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
114
|
+
def test_formatter_returns_json
|
|
115
|
+
get '/grape/render'
|
|
116
|
+
|
|
117
|
+
post = Models.model1
|
|
118
|
+
serializable_resource = serializable(post)
|
|
50
119
|
|
|
51
|
-
|
|
52
|
-
|
|
120
|
+
assert last_response.ok?
|
|
121
|
+
assert_equal serializable_resource.to_json, last_response.body
|
|
122
|
+
end
|
|
53
123
|
|
|
54
|
-
|
|
55
|
-
|
|
124
|
+
def test_render_helper_passes_through_options_correctly
|
|
125
|
+
get '/grape/render_with_json_api'
|
|
56
126
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
end
|
|
127
|
+
post = Models.model1
|
|
128
|
+
serializable_resource = serializable(post, serializer: ARModels::PostSerializer, adapter: :json_api, meta: { page: 1, total_pages: 2 })
|
|
60
129
|
|
|
61
|
-
|
|
62
|
-
|
|
130
|
+
assert last_response.ok?
|
|
131
|
+
assert_equal serializable_resource.to_json, last_response.body
|
|
132
|
+
end
|
|
63
133
|
|
|
64
|
-
|
|
65
|
-
|
|
134
|
+
def test_formatter_handles_arrays
|
|
135
|
+
get '/grape/render_array_with_json_api'
|
|
66
136
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
end
|
|
137
|
+
posts = Models.all
|
|
138
|
+
serializable_resource = serializable(posts, adapter: :json_api)
|
|
70
139
|
|
|
71
|
-
|
|
72
|
-
|
|
140
|
+
assert last_response.ok?
|
|
141
|
+
assert_equal serializable_resource.to_json, last_response.body
|
|
142
|
+
ensure
|
|
143
|
+
Models.reset_all
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_formatter_handles_collections
|
|
147
|
+
get '/grape/render_collection_with_json_api'
|
|
148
|
+
assert last_response.ok?
|
|
73
149
|
|
|
74
|
-
|
|
75
|
-
|
|
150
|
+
representation = JSON.parse(last_response.body)
|
|
151
|
+
assert representation.include?('data')
|
|
152
|
+
assert representation['data'].count == Models.collection_per
|
|
153
|
+
assert representation.include?('links')
|
|
154
|
+
assert representation['links'].count > 0
|
|
155
|
+
end
|
|
76
156
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
157
|
+
def test_implicit_formatter
|
|
158
|
+
post = Models.model1
|
|
159
|
+
serializable_resource = serializable(post, adapter: :json_api)
|
|
160
|
+
|
|
161
|
+
with_adapter :json_api do
|
|
162
|
+
get '/grape/render_with_implicit_formatter'
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
assert last_response.ok?
|
|
166
|
+
assert_equal serializable_resource.to_json, last_response.body
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def test_implicit_formatter_handles_arrays
|
|
170
|
+
posts = Models.all
|
|
171
|
+
serializable_resource = serializable(posts, adapter: :json_api)
|
|
172
|
+
|
|
173
|
+
with_adapter :json_api do
|
|
174
|
+
get '/grape/render_array_with_implicit_formatter'
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
assert last_response.ok?
|
|
178
|
+
assert_equal serializable_resource.to_json, last_response.body
|
|
179
|
+
ensure
|
|
180
|
+
Models.reset_all
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def test_implicit_formatter_handles_collections
|
|
184
|
+
with_adapter :json_api do
|
|
185
|
+
get '/grape/render_collection_with_implicit_formatter'
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
representation = JSON.parse(last_response.body)
|
|
189
|
+
assert last_response.ok?
|
|
190
|
+
assert representation.include?('data')
|
|
191
|
+
assert representation['data'].count == Models.collection_per
|
|
192
|
+
assert representation.include?('links')
|
|
193
|
+
assert representation['links'].count > 0
|
|
194
|
+
end
|
|
81
195
|
end
|
|
82
196
|
end
|