active_model_serializers 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -4
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +9 -1
  5. data/Rakefile +3 -3
  6. data/active_model_serializers.gemspec +15 -15
  7. data/docs/general/fields.md +31 -0
  8. data/docs/general/rendering.md +7 -2
  9. data/docs/general/serializers.md +32 -0
  10. data/docs/howto/add_pagination_links.md +2 -3
  11. data/docs/integrations/ember-and-json-api.md +25 -10
  12. data/lib/action_controller/serialization.rb +4 -3
  13. data/lib/active_model/serializer.rb +3 -4
  14. data/lib/active_model/serializer/array_serializer.rb +8 -5
  15. data/lib/active_model/serializer/associations.rb +2 -2
  16. data/lib/active_model/serializer/caching.rb +11 -8
  17. data/lib/active_model/serializer/error_serializer.rb +11 -7
  18. data/lib/active_model/serializer/errors_serializer.rb +25 -20
  19. data/lib/active_model/serializer/lint.rb +134 -130
  20. data/lib/active_model/serializer/version.rb +1 -1
  21. data/lib/active_model_serializers/deprecate.rb +1 -1
  22. data/lib/active_model_serializers/model.rb +1 -1
  23. data/lib/active_model_serializers/railtie.rb +1 -1
  24. data/lib/active_model_serializers/register_jsonapi_renderer.rb +37 -35
  25. data/lib/generators/rails/serializer_generator.rb +3 -3
  26. data/lib/grape/active_model_serializers.rb +7 -5
  27. data/test/action_controller/adapter_selector_test.rb +3 -3
  28. data/test/action_controller/json_api/errors_test.rb +5 -6
  29. data/test/action_controller/json_api/linked_test.rb +4 -4
  30. data/test/action_controller/json_api/pagination_test.rb +19 -19
  31. data/test/action_controller/serialization_test.rb +1 -1
  32. data/test/active_model_serializers/json_pointer_test.rb +15 -13
  33. data/test/active_model_serializers/key_transform_test.rb +254 -252
  34. data/test/active_model_serializers/model_test.rb +6 -4
  35. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +2 -2
  36. data/test/adapter/json/transform_test.rb +14 -14
  37. data/test/adapter/json_api/errors_test.rb +9 -9
  38. data/test/adapter/json_api/has_many_test.rb +18 -18
  39. data/test/adapter/json_api/json_api_test.rb +5 -7
  40. data/test/adapter/json_api/linked_test.rb +1 -1
  41. data/test/adapter/json_api/pagination_links_test.rb +6 -6
  42. data/test/adapter/json_api/resource_meta_test.rb +3 -3
  43. data/test/adapter/json_api/transform_test.rb +218 -218
  44. data/test/adapter/json_api/type_test.rb +1 -1
  45. data/test/adapter/json_test.rb +8 -8
  46. data/test/adapter/null_test.rb +1 -2
  47. data/test/adapter/polymorphic_test.rb +5 -5
  48. data/test/adapter_test.rb +1 -1
  49. data/test/benchmark/bm_caching.rb +1 -1
  50. data/test/cache_test.rb +29 -1
  51. data/test/collection_serializer_test.rb +2 -2
  52. data/test/fixtures/poro.rb +2 -2
  53. data/test/grape_test.rb +130 -128
  54. data/test/lint_test.rb +1 -1
  55. data/test/logger_test.rb +13 -11
  56. data/test/serializable_resource_test.rb +12 -16
  57. data/test/serializers/associations_test.rb +10 -10
  58. data/test/serializers/attribute_test.rb +1 -1
  59. data/test/serializers/attributes_test.rb +1 -1
  60. data/test/serializers/fieldset_test.rb +1 -1
  61. data/test/serializers/root_test.rb +1 -1
  62. data/test/serializers/serializer_for_test.rb +3 -1
  63. data/test/support/isolated_unit.rb +4 -2
  64. data/test/support/serialization_testing.rb +7 -5
  65. metadata +3 -3
  66. data/.rubocop_todo.yml +0 -167
@@ -47,7 +47,7 @@ module ActiveModel
47
47
  assert_equal(expected_type, hash.fetch(:data).fetch(:type))
48
48
  end
49
49
 
50
- def with_jsonapi_resource_type inflection
50
+ def with_jsonapi_resource_type(inflection)
51
51
  old_inflection = ActiveModelSerializers.config.jsonapi_resource_type
52
52
  ActiveModelSerializers.config.jsonapi_resource_type = inflection
53
53
  yield
@@ -32,14 +32,14 @@ module ActiveModelSerializers
32
32
  adapter = ActiveModelSerializers::Adapter::Json.new(serializer)
33
33
 
34
34
  assert_equal({
35
- id: 1,
36
- reviews: [
37
- { id: 1, body: 'ZOMG A COMMENT' },
38
- { id: 2, body: 'ZOMG ANOTHER COMMENT' }
39
- ],
40
- writer: { id: 1, name: 'Steve K.' },
41
- site: { id: 1, name: 'My Blog!!' }
42
- }, adapter.serializable_hash[:post])
35
+ id: 1,
36
+ reviews: [
37
+ { id: 1, body: 'ZOMG A COMMENT' },
38
+ { id: 2, body: 'ZOMG ANOTHER COMMENT' }
39
+ ],
40
+ writer: { id: 1, name: 'Steve K.' },
41
+ site: { id: 1, name: 'My Blog!!' }
42
+ }, adapter.serializable_hash[:post])
43
43
  end
44
44
  end
45
45
  end
@@ -4,7 +4,7 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class NullTest < ActiveSupport::TestCase
6
6
  def setup
7
- profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
7
+ profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
8
8
  serializer = ProfileSerializer.new(profile)
9
9
 
10
10
  @adapter = Null.new(serializer)
@@ -20,4 +20,3 @@ module ActiveModelSerializers
20
20
  end
21
21
  end
22
22
  end
23
-
@@ -27,11 +27,11 @@ module ActiveModel
27
27
  id: 1,
28
28
  title: 'headshot-1.jpg',
29
29
  imageable: {
30
- type: 'employee',
31
- employee: {
32
- id: 42,
33
- name: 'Zoop Zoopler'
34
- }
30
+ type: 'employee',
31
+ employee: {
32
+ id: 42,
33
+ name: 'Zoop Zoopler'
34
+ }
35
35
  }
36
36
  }
37
37
 
@@ -51,7 +51,7 @@ module ActiveModelSerializers
51
51
  end
52
52
 
53
53
  def test_create_adapter_with_override
54
- adapter = ActiveModelSerializers::Adapter.create(@serializer, { adapter: :json_api })
54
+ adapter = ActiveModelSerializers::Adapter.create(@serializer, adapter: :json_api)
55
55
  assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
56
56
  end
57
57
 
@@ -86,7 +86,7 @@ class ApiAssertion
86
86
  }
87
87
  ]
88
88
  }
89
- }
89
+ }
90
90
  end
91
91
 
92
92
  def assert_equal(expected, actual, message)
@@ -101,7 +101,7 @@ module ActiveModelSerializers
101
101
  uncached_author_serializer = AuthorSerializer.new(uncached_author)
102
102
 
103
103
  render_object_with_cache(uncached_author)
104
- key = "#{uncached_author_serializer.class._cache_key}/#{uncached_author_serializer.object.id}-#{uncached_author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}"
104
+ key = "#{uncached_author_serializer.class._cache_key}/#{uncached_author_serializer.object.id}-#{uncached_author_serializer.object.updated_at.strftime('%Y%m%d%H%M%S%9N')}"
105
105
  key = "#{key}/#{adapter.cache_key}"
106
106
  assert_equal(uncached_author_serializer.attributes.to_json, cache_store.fetch(key).to_json)
107
107
  end
@@ -321,6 +321,34 @@ module ActiveModelSerializers
321
321
  end
322
322
  end
323
323
 
324
+ def test_cache_read_multi_with_fragment_cache_enabled
325
+ post_serializer = Class.new(ActiveModel::Serializer) do
326
+ cache except: [:body]
327
+ end
328
+
329
+ serializers = ActiveModel::Serializer::CollectionSerializer.new([@post, @post], serializer: post_serializer)
330
+
331
+ Timecop.freeze(Time.current) do
332
+ # Warming up.
333
+ options = {}
334
+ adapter_options = {}
335
+ adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(serializers, adapter_options)
336
+ serializers.serializable_hash(adapter_options, options, adapter_instance)
337
+
338
+ # Should find something with read_multi now
339
+ adapter_options = {}
340
+ serializers.serializable_hash(adapter_options, options, adapter_instance)
341
+ cached_attributes = adapter_options.fetch(:cached_attributes)
342
+
343
+ include_directive = ActiveModelSerializers.default_include_directive
344
+ manual_cached_attributes = ActiveModel::Serializer.cache_read_multi(serializers, adapter_instance, include_directive)
345
+
346
+ refute_equal 0, cached_attributes.size
347
+ refute_equal 0, manual_cached_attributes.size
348
+ assert_equal manual_cached_attributes, cached_attributes
349
+ end
350
+ end
351
+
324
352
  def test_serializer_file_path_on_nix
325
353
  path = '/Users/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb'
326
354
  caller_line = "#{path}:1:in `<top (required)>'"
@@ -11,7 +11,7 @@ module ActiveModel
11
11
  @comment = Comment.new
12
12
  @post = Post.new
13
13
  @resource = build_named_collection @comment, @post
14
- @serializer = collection_serializer.new(@resource, { some: :options })
14
+ @serializer = collection_serializer.new(@resource, some: :options)
15
15
  end
16
16
 
17
17
  def collection_serializer
@@ -44,7 +44,7 @@ module ActiveModel
44
44
  end
45
45
 
46
46
  def test_serializer_option_not_passed_to_each_serializer
47
- serializers = collection_serializer.new([@post], { serializer: PostSerializer }).to_a
47
+ serializers = collection_serializer.new([@post], serializer: PostSerializer).to_a
48
48
 
49
49
  refute serializers.first.custom_options.key?(:serializer)
50
50
  end
@@ -8,7 +8,7 @@ class Model < ActiveModelSerializers::Model
8
8
  # Convenience when not adding @attributes readers and writers
9
9
  def method_missing(meth, *args)
10
10
  if meth.to_s =~ /^(.*)=$/
11
- attributes[$1.to_sym] = args[0]
11
+ attributes[Regexp.last_match(1).to_sym] = args[0]
12
12
  elsif attributes.key?(meth)
13
13
  attributes[meth]
14
14
  else
@@ -64,7 +64,7 @@ VirtualValue = Class.new(Model)
64
64
  Comment = Class.new(Model) do
65
65
  # Uses a custom non-time-based cache key
66
66
  def cache_key
67
- "#{self.class.name.downcase}/#{self.id}"
67
+ "#{self.class.name.downcase}/#{id}"
68
68
  end
69
69
  end
70
70
 
@@ -5,172 +5,174 @@ require 'kaminari'
5
5
  require 'kaminari/hooks'
6
6
  ::Kaminari::Hooks.init
7
7
 
8
- class ActiveModelSerializers::GrapeTest < ActiveSupport::TestCase
9
- include Rack::Test::Methods
10
- module Models
11
- def self.model1
12
- ARModels::Post.new(id: 1, title: 'Dummy Title', body: 'Lorem Ipsum')
13
- end
8
+ module ActiveModelSerializers
9
+ class GrapeTest < ActiveSupport::TestCase
10
+ include Rack::Test::Methods
11
+ module Models
12
+ def self.model1
13
+ ARModels::Post.new(id: 1, title: 'Dummy Title', body: 'Lorem Ipsum')
14
+ end
14
15
 
15
- def self.model2
16
- ARModels::Post.new(id: 2, title: 'Second Dummy Title', body: 'Second Lorem Ipsum')
17
- end
16
+ def self.model2
17
+ ARModels::Post.new(id: 2, title: 'Second Dummy Title', body: 'Second Lorem Ipsum')
18
+ end
18
19
 
19
- def self.all
20
- @all ||=
21
- begin
22
- model1.save!
23
- model2.save!
24
- ARModels::Post.all
25
- end
26
- end
20
+ def self.all
21
+ @all ||=
22
+ begin
23
+ model1.save!
24
+ model2.save!
25
+ ARModels::Post.all
26
+ end
27
+ end
27
28
 
28
- def self.reset_all
29
- ARModels::Post.delete_all
30
- @all = nil
31
- end
29
+ def self.reset_all
30
+ ARModels::Post.delete_all
31
+ @all = nil
32
+ end
32
33
 
33
- def self.collection_per
34
- 2
35
- end
34
+ def self.collection_per
35
+ 2
36
+ end
36
37
 
37
- def self.collection
38
- @collection ||=
39
- begin
40
- Kaminari.paginate_array(
41
- [
42
- Profile.new(id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
43
- Profile.new(id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
44
- Profile.new(id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3'),
45
- Profile.new(id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4'),
46
- Profile.new(id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5')
38
+ def self.collection
39
+ @collection ||=
40
+ begin
41
+ Kaminari.paginate_array(
42
+ [
43
+ Profile.new(id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
44
+ Profile.new(id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
45
+ Profile.new(id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3'),
46
+ Profile.new(id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4'),
47
+ Profile.new(id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5')
47
48
  ]
48
- ).page(1).per(collection_per)
49
- end
49
+ ).page(1).per(collection_per)
50
+ end
51
+ end
50
52
  end
51
- end
52
53
 
53
- class GrapeTest < Grape::API
54
- format :json
55
- include Grape::ActiveModelSerializers
54
+ class GrapeTest < Grape::API
55
+ format :json
56
+ include Grape::ActiveModelSerializers
56
57
 
57
- resources :grape do
58
- get '/render' do
59
- render Models.model1
60
- end
58
+ resources :grape do
59
+ get '/render' do
60
+ render Models.model1
61
+ end
61
62
 
62
- get '/render_with_json_api' do
63
- post = Models.model1
64
- render post, meta: { page: 1, total_pages: 2 }, adapter: :json_api
65
- end
63
+ get '/render_with_json_api' do
64
+ post = Models.model1
65
+ render post, meta: { page: 1, total_pages: 2 }, adapter: :json_api
66
+ end
66
67
 
67
- get '/render_array_with_json_api' do
68
- posts = Models.all
69
- render posts, adapter: :json_api
70
- end
68
+ get '/render_array_with_json_api' do
69
+ posts = Models.all
70
+ render posts, adapter: :json_api
71
+ end
71
72
 
72
- get '/render_collection_with_json_api' do
73
- posts = Models.collection
74
- render posts, adapter: :json_api
75
- end
73
+ get '/render_collection_with_json_api' do
74
+ posts = Models.collection
75
+ render posts, adapter: :json_api
76
+ end
76
77
 
77
- get '/render_with_implicit_formatter' do
78
- Models.model1
79
- end
78
+ get '/render_with_implicit_formatter' do
79
+ Models.model1
80
+ end
80
81
 
81
- get '/render_array_with_implicit_formatter' do
82
- Models.all
83
- end
82
+ get '/render_array_with_implicit_formatter' do
83
+ Models.all
84
+ end
84
85
 
85
- get '/render_collection_with_implicit_formatter' do
86
- Models.collection
86
+ get '/render_collection_with_implicit_formatter' do
87
+ Models.collection
88
+ end
87
89
  end
88
90
  end
89
- end
90
91
 
91
- def app
92
- Grape::Middleware::Globals.new(GrapeTest.new)
93
- end
92
+ def app
93
+ Grape::Middleware::Globals.new(GrapeTest.new)
94
+ end
94
95
 
95
- def test_formatter_returns_json
96
- get '/grape/render'
96
+ def test_formatter_returns_json
97
+ get '/grape/render'
97
98
 
98
- post = Models.model1
99
- serializable_resource = serializable(post)
99
+ post = Models.model1
100
+ serializable_resource = serializable(post)
100
101
 
101
- assert last_response.ok?
102
- assert_equal serializable_resource.to_json, last_response.body
103
- end
102
+ assert last_response.ok?
103
+ assert_equal serializable_resource.to_json, last_response.body
104
+ end
104
105
 
105
- def test_render_helper_passes_through_options_correctly
106
- get '/grape/render_with_json_api'
106
+ def test_render_helper_passes_through_options_correctly
107
+ get '/grape/render_with_json_api'
107
108
 
108
- post = Models.model1
109
- serializable_resource = serializable(post, serializer: ARModels::PostSerializer, adapter: :json_api, meta: { page: 1, total_pages: 2 })
109
+ post = Models.model1
110
+ serializable_resource = serializable(post, serializer: ARModels::PostSerializer, adapter: :json_api, meta: { page: 1, total_pages: 2 })
110
111
 
111
- assert last_response.ok?
112
- assert_equal serializable_resource.to_json, last_response.body
113
- end
112
+ assert last_response.ok?
113
+ assert_equal serializable_resource.to_json, last_response.body
114
+ end
114
115
 
115
- def test_formatter_handles_arrays
116
- get '/grape/render_array_with_json_api'
116
+ def test_formatter_handles_arrays
117
+ get '/grape/render_array_with_json_api'
117
118
 
118
- posts = Models.all
119
- serializable_resource = serializable(posts, adapter: :json_api)
119
+ posts = Models.all
120
+ serializable_resource = serializable(posts, adapter: :json_api)
120
121
 
121
- assert last_response.ok?
122
- assert_equal serializable_resource.to_json, last_response.body
123
- ensure
124
- Models.reset_all
125
- end
122
+ assert last_response.ok?
123
+ assert_equal serializable_resource.to_json, last_response.body
124
+ ensure
125
+ Models.reset_all
126
+ end
126
127
 
127
- def test_formatter_handles_collections
128
- get '/grape/render_collection_with_json_api'
129
- assert last_response.ok?
128
+ def test_formatter_handles_collections
129
+ get '/grape/render_collection_with_json_api'
130
+ assert last_response.ok?
130
131
 
131
- representation = JSON.parse(last_response.body)
132
- assert representation.include?('data')
133
- assert representation['data'].count == Models.collection_per
134
- assert representation.include?('links')
135
- assert representation['links'].count > 0
136
- end
132
+ representation = JSON.parse(last_response.body)
133
+ assert representation.include?('data')
134
+ assert representation['data'].count == Models.collection_per
135
+ assert representation.include?('links')
136
+ assert representation['links'].count > 0
137
+ end
138
+
139
+ def test_implicit_formatter
140
+ post = Models.model1
141
+ serializable_resource = serializable(post, adapter: :json_api)
137
142
 
138
- def test_implicit_formatter
139
- post = Models.model1
140
- serializable_resource = serializable(post, adapter: :json_api)
143
+ with_adapter :json_api do
144
+ get '/grape/render_with_implicit_formatter'
145
+ end
141
146
 
142
- with_adapter :json_api do
143
- get '/grape/render_with_implicit_formatter'
147
+ assert last_response.ok?
148
+ assert_equal serializable_resource.to_json, last_response.body
144
149
  end
145
150
 
146
- assert last_response.ok?
147
- assert_equal serializable_resource.to_json, last_response.body
148
- end
151
+ def test_implicit_formatter_handles_arrays
152
+ posts = Models.all
153
+ serializable_resource = serializable(posts, adapter: :json_api)
149
154
 
150
- def test_implicit_formatter_handles_arrays
151
- posts = Models.all
152
- serializable_resource = serializable(posts, adapter: :json_api)
155
+ with_adapter :json_api do
156
+ get '/grape/render_array_with_implicit_formatter'
157
+ end
153
158
 
154
- with_adapter :json_api do
155
- get '/grape/render_array_with_implicit_formatter'
159
+ assert last_response.ok?
160
+ assert_equal serializable_resource.to_json, last_response.body
161
+ ensure
162
+ Models.reset_all
156
163
  end
157
164
 
158
- assert last_response.ok?
159
- assert_equal serializable_resource.to_json, last_response.body
160
- ensure
161
- Models.reset_all
162
- end
165
+ def test_implicit_formatter_handles_collections
166
+ with_adapter :json_api do
167
+ get '/grape/render_collection_with_implicit_formatter'
168
+ end
163
169
 
164
- def test_implicit_formatter_handles_collections
165
- with_adapter :json_api do
166
- get '/grape/render_collection_with_implicit_formatter'
170
+ representation = JSON.parse(last_response.body)
171
+ assert last_response.ok?
172
+ assert representation.include?('data')
173
+ assert representation['data'].count == Models.collection_per
174
+ assert representation.include?('links')
175
+ assert representation['links'].count > 0
167
176
  end
168
-
169
- representation = JSON.parse(last_response.body)
170
- assert last_response.ok?
171
- assert representation.include?('data')
172
- assert representation['data'].count == Models.collection_per
173
- assert representation.include?('links')
174
- assert representation['links'].count > 0
175
177
  end
176
178
  end