active_model_serializers 0.10.1 → 0.10.2

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.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01b7ca6e2acce14a076a2a63c87dc6d4677989dc
4
- data.tar.gz: e04babe194acff0c4a0fd2b1daec6ee5128d8b8d
3
+ metadata.gz: d9ab72fd33fbf20e8630b9109d18edda9272658e
4
+ data.tar.gz: 8654e40594d8bf26038b329a8044dc9197bc5733
5
5
  SHA512:
6
- metadata.gz: 5b4a986b9ab49ec7962be0ff855c9c3d2504e55743b8ba5cbbb22fdb936704456d5033160ab52d5efc2537a248f18de636aaafc7d5ec9c8a29a5e027f1c39063
7
- data.tar.gz: d824f39238f997d1fd763f8cb8d6ce158209a7d4c3ab5de3ea5294d991e5f2a6a1dca6a2be090bc69195ed58506ae54e5934f61440095ab2a749a948397a6937
6
+ metadata.gz: 454504b650ab8302e6e1f87b15f952ff3068033bcaaac136764211fbcb724759b354d66b7e0b662e1e10a1b57734173b4843f96eb2344c164d568fae824da8b3
7
+ data.tar.gz: 56355761907c1ea7882d7b04dc8adcff8538f188bd418946c2493a267188cedfef4247e410206b4c479575ba926efa1259c5966e166b901eaea26c45b7d4aae8
@@ -1,7 +1,5 @@
1
- inherit_from: .rubocop_todo.yml
2
-
3
1
  AllCops:
4
- TargetRubyVersion: 2.2
2
+ TargetRubyVersion: 2.1
5
3
  Exclude:
6
4
  - config/initializers/forbidden_yaml.rb
7
5
  - !ruby/regexp /(vendor|bundle|bin|db|tmp)\/.*/
@@ -46,7 +44,7 @@ Style/AlignParameters:
46
44
  EnforcedStyle: with_fixed_indentation
47
45
 
48
46
  Style/ClassAndModuleChildren:
49
- EnforcedStyle: compact
47
+ EnforcedStyle: nested
50
48
 
51
49
  Style/Documentation:
52
50
  Enabled: false
@@ -27,6 +27,7 @@ env:
27
27
  matrix:
28
28
  - "RAILS_VERSION=4.1"
29
29
  - "RAILS_VERSION=4.2"
30
+ - "RAILS_VERSION=5.0"
30
31
  - "RAILS_VERSION=master"
31
32
 
32
33
  matrix:
@@ -1,6 +1,6 @@
1
1
  ## 0.10.x
2
2
 
3
- ### [master (unreleased)](https://github.com/rails-api/active_model_serializers/compare/v0.10.1...master)
3
+ ### [master (unreleased)](https://github.com/rails-api/active_model_serializers/compare/v0.10.2...master)
4
4
 
5
5
  Breaking changes:
6
6
 
@@ -10,6 +10,14 @@ Fixes:
10
10
 
11
11
  Misc:
12
12
 
13
+ ### [v0.10.2 (2016-07-05)(unreleased)](https://github.com/rails-api/active_model_serializers/compare/v0.10.1...v0.10.2)
14
+
15
+ Fixes:
16
+ - [#1814] (https://github.com/rails-api/active_model_serializers/pull/1814) Ensuring read_multi works with fragment cache
17
+
18
+ Misc:
19
+ - [#1808](https://github.com/rails-api/active_model_serializers/pull/1808) Adds documentation for `fields` option. (@luizkowalski)
20
+
13
21
  ### [v0.10.1 (2016-06-16)](https://github.com/rails-api/active_model_serializers/compare/v0.10.0...v0.10.1)
14
22
 
15
23
  Features:
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ rescue LoadError
5
5
  end
6
6
  begin
7
7
  require 'simplecov'
8
- rescue LoadError
8
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
9
9
  end
10
10
 
11
11
  Bundler::GemHelper.install_tasks
@@ -33,7 +33,7 @@ end
33
33
  begin
34
34
  require 'rubocop'
35
35
  require 'rubocop/rake_task'
36
- rescue LoadError
36
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
37
37
  else
38
38
  Rake::Task[:rubocop].clear if Rake::Task.task_defined?(:rubocop)
39
39
  require 'rbconfig'
@@ -100,4 +100,4 @@ else
100
100
  end
101
101
 
102
102
  desc 'CI test task'
103
- task :ci => [:default]
103
+ task ci: [:default]
@@ -23,31 +23,31 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  rails_versions = ['>= 4.1', '< 6']
25
25
  spec.add_runtime_dependency 'activemodel', rails_versions
26
- # 'activesupport', rails_versions
27
- # 'builder'
26
+ # 'activesupport', rails_versions
27
+ # 'builder'
28
28
 
29
29
  spec.add_runtime_dependency 'actionpack', rails_versions
30
- # 'activesupport', rails_versions
31
- # 'rack'
32
- # 'rack-test', '~> 0.6.2'
30
+ # 'activesupport', rails_versions
31
+ # 'rack'
32
+ # 'rack-test', '~> 0.6.2'
33
33
 
34
34
  spec.add_runtime_dependency 'railties', rails_versions
35
- # 'activesupport', rails_versions
36
- # 'actionpack', rails_versions
37
- # 'rake', '>= 0.8.7'
35
+ # 'activesupport', rails_versions
36
+ # 'actionpack', rails_versions
37
+ # 'rake', '>= 0.8.7'
38
38
 
39
39
  # 'activesupport', rails_versions
40
- # 'i18n,
41
- # 'tzinfo'
42
- # 'minitest'
43
- # 'thread_safe'
40
+ # 'i18n,
41
+ # 'tzinfo'
42
+ # 'minitest'
43
+ # 'thread_safe'
44
44
 
45
45
  spec.add_runtime_dependency 'jsonapi', '~> 0.1.1.beta2'
46
46
 
47
47
  spec.add_development_dependency 'activerecord', rails_versions
48
- # arel
49
- # activesupport
50
- # activemodel
48
+ # arel
49
+ # activesupport
50
+ # activemodel
51
51
 
52
52
  # Soft dependency for pagination
53
53
  spec.add_development_dependency 'kaminari', ' ~> 0.16.3'
@@ -0,0 +1,31 @@
1
+ [Back to Guides](../README.md)
2
+
3
+ # Fields
4
+
5
+ If for any reason, you need to restrict the fields returned, you should use `fields` option.
6
+
7
+ For example, if you have a serializer like this
8
+
9
+ ```ruby
10
+ class UserSerializer < ActiveModel::Serializer
11
+ attributes :access_token, :first_name, :last_name
12
+ end
13
+ ```
14
+
15
+ and in a specific controller, you want to return `access_token` only, `fields` will help you:
16
+
17
+ ```ruby
18
+ class AnonymousController < ApplicationController
19
+ def create
20
+ render json: User.create(activation_state: 'anonymous'), fields: [:access_token], status: 201
21
+ end
22
+ end
23
+ ```
24
+
25
+ Note that this is only valid for the `json` and `attributes` adapter. For the `json_api` adapter, you would use
26
+
27
+ ```ruby
28
+ render json: @user, fields: { users: [:access_token] }
29
+ ```
30
+
31
+ Where `users` is the JSONAPI type.
@@ -73,7 +73,12 @@ See [ARCHITECTURE](../ARCHITECTURE.md) for more information.
73
73
 
74
74
  #### fields
75
75
 
76
- PR please :)
76
+ If you are using `json` or `attributes` adapter
77
+ ```ruby
78
+ render json: @user, fields: [:access_token]
79
+ ```
80
+
81
+ See [Fields](fields.md) for more information.
77
82
 
78
83
  #### adapter
79
84
 
@@ -83,7 +88,7 @@ PR please :)
83
88
 
84
89
  ```render json: posts, each_serializer: PostSerializer, key_transform: :camel_lower```
85
90
 
86
- See [Key Transforms](key_transforms.md) for more informaiton.
91
+ See [Key Transforms](key_transforms.md) for more information.
87
92
 
88
93
  #### meta
89
94
 
@@ -314,6 +314,38 @@ So that when we render the `#edit` action, we'll get
314
314
 
315
315
  Where `can_edit` is `view_context.current_user.admin?` (true).
316
316
 
317
+ You can also tell what to set as `serialization_scope` for specific actions.
318
+
319
+ For example, use `admin_user` only for `Admin::PostSerializer` and `current_user` for rest.
320
+
321
+ ```ruby
322
+ class PostsController < ActionController::Base
323
+
324
+ before_action only: :edit do
325
+ self.class.serialization_scope :admin_user
326
+ end
327
+
328
+ def show
329
+ render json: @post, serializer: PostSerializer
330
+ end
331
+
332
+ def edit
333
+ @post.save
334
+ render json: @post, serializer: Admin::PostSerializer
335
+ end
336
+
337
+ private
338
+
339
+ def admin_user
340
+ User.new(id: 2, name: 'Bob', admin: true)
341
+ end
342
+
343
+ def current_user
344
+ User.new(id: 2, name: 'Bob', admin: false)
345
+ end
346
+ end
347
+ ```
348
+
317
349
  #### #read_attribute_for_serialization(key)
318
350
 
319
351
  The serialized value for a given key. e.g. `read_attribute_for_serialization(:title) #=> 'Hello World'`
@@ -81,7 +81,7 @@ def pagination_dict(object)
81
81
  {
82
82
  current_page: object.current_page,
83
83
  next_page: object.next_page,
84
- prev_page: object.prev_page,
84
+ prev_page: object.prev_page, # use object.previous_page when using will_paginate
85
85
  total_pages: object.total_pages,
86
86
  total_count: object.total_count
87
87
  }
@@ -126,14 +126,13 @@ def meta_attributes(resource, extra_meta = {})
126
126
  {
127
127
  current_page: resource.current_page,
128
128
  next_page: resource.next_page,
129
- prev_page: resource.prev_page,
129
+ prev_page: resource.prev_page, # use resource.previous_page when using will_paginate
130
130
  total_pages: resource.total_pages,
131
131
  total_count: resource.total_count
132
132
  }.merge(extra_meta)
133
133
  end
134
134
  ```
135
135
 
136
-
137
136
  ### Attributes adapter
138
137
 
139
138
  This adapter does not allow us to use `meta` key, due to that it is not possible to add pagination links.
@@ -17,17 +17,32 @@ To solve this, in Ember, both the adapter and the serializer will need some modi
17
17
 
18
18
  ### Server-Side Changes
19
19
 
20
- there are multiple mimetypes for json that should all be parsed similarly, so
21
- in `config/initializers/mime_types.rb`:
20
+ First, set the adapter type in an initializer file:
21
+
22
+ ```ruby
23
+ # config/initializers/active_model_serializers.rb
24
+ ActiveModelSerializers.config.adapter = :json_api
25
+ ```
26
+
27
+ or:
28
+
29
+ ```ruby
30
+ # config/initializers/active_model_serializers.rb
31
+ ActiveModelSerializers.config.adapter = ActiveModelSerializers::Adapter::JsonApi
32
+ ```
33
+
34
+ You will also want to set the `key_transform` to `:unaltered` since you will adjust the attributes in your Ember serializer to use underscores instead of dashes later. You could also use `:underscore`, but `:unaltered` is better for performance.
35
+
36
+ ```ruby
37
+ # config/initializers/active_model_serializers.rb
38
+ ActiveModelSerializers.config.key_transform = :unaltered
39
+ ```
40
+
41
+ Lastly, in order to properly handle JSON API responses, we need to register a JSON API renderer, like so:
42
+
22
43
  ```ruby
23
- api_mime_types = %W(
24
- application/vnd.api+json
25
- text/x-json
26
- application/json
27
- )
28
-
29
- Mime::Type.unregister :json
30
- Mime::Type.register 'application/json', :json, api_mime_types
44
+ # config/initializers/active_model_serializers.rb
45
+ require 'active_model_serializers/register_jsonapi_renderer'
31
46
  ```
32
47
 
33
48
  ### Adapter Changes
@@ -19,12 +19,13 @@ module ActionController
19
19
  end
20
20
 
21
21
  def serialization_scope
22
- send(_serialization_scope) if _serialization_scope &&
23
- respond_to?(_serialization_scope, true)
22
+ return unless _serialization_scope && respond_to?(_serialization_scope, true)
23
+
24
+ send(_serialization_scope)
24
25
  end
25
26
 
26
27
  def get_serializer(resource, options = {})
27
- if !use_adapter?
28
+ unless use_adapter?
28
29
  warn 'ActionController::Serialization#use_adapter? has been removed. '\
29
30
  "Please pass 'adapter: false' or see ActiveSupport::SerializableResource.new"
30
31
  options[:adapter] = false
@@ -125,10 +125,9 @@ module ActiveModel
125
125
  self.root = instance_options[:root]
126
126
  self.scope = instance_options[:scope]
127
127
 
128
- scope_name = instance_options[:scope_name]
129
- if scope_name && !respond_to?(scope_name)
130
- define_singleton_method scope_name, lambda { scope }
131
- end
128
+ return if !(scope_name = instance_options[:scope_name]) || respond_to?(scope_name)
129
+
130
+ define_singleton_method scope_name, -> { scope }
132
131
  end
133
132
 
134
133
  def success?
@@ -1,9 +1,12 @@
1
1
  require 'active_model/serializer/collection_serializer'
2
- class ActiveModel::Serializer
3
- class ArraySerializer < CollectionSerializer
4
- class << self
5
- extend ActiveModelSerializers::Deprecate
6
- deprecate :new, 'ActiveModel::Serializer::CollectionSerializer.'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class ArraySerializer < CollectionSerializer
6
+ class << self
7
+ extend ActiveModelSerializers::Deprecate
8
+ deprecate :new, 'ActiveModel::Serializer::CollectionSerializer.'
9
+ end
7
10
  end
8
11
  end
9
12
  end
@@ -39,7 +39,7 @@ module ActiveModel
39
39
  # @example
40
40
  # has_many :comments, serializer: CommentSummarySerializer
41
41
  #
42
- def has_many(name, options = {}, &block)
42
+ def has_many(name, options = {}, &block) # rubocop:disable Style/PredicateName
43
43
  associate(HasManyReflection.new(name, options, block))
44
44
  end
45
45
 
@@ -61,7 +61,7 @@ module ActiveModel
61
61
  # @example
62
62
  # has_one :author, serializer: AuthorSerializer
63
63
  #
64
- def has_one(name, options = {}, &block)
64
+ def has_one(name, options = {}, &block) # rubocop:disable Style/PredicateName
65
65
  associate(HasOneReflection.new(name, options, block))
66
66
  end
67
67
 
@@ -197,7 +197,7 @@ module ActiveModel
197
197
  def object_cache_key(serializer, adapter_instance)
198
198
  return unless serializer.present? && serializer.object.present?
199
199
 
200
- serializer.class.cache_enabled? ? serializer.cache_key(adapter_instance) : nil
200
+ (serializer.class.cache_enabled? || serializer.class.fragment_cache_enabled?) ? serializer.cache_key(adapter_instance) : nil
201
201
  end
202
202
  end
203
203
 
@@ -211,7 +211,7 @@ module ActiveModel
211
211
  end
212
212
  end
213
213
  elsif serializer_class.fragment_cache_enabled?
214
- fetch_attributes_fragment(adapter_instance)
214
+ fetch_attributes_fragment(adapter_instance, cached_attributes)
215
215
  else
216
216
  attributes(fields, true)
217
217
  end
@@ -230,7 +230,8 @@ module ActiveModel
230
230
  # 1. Determine cached fields from serializer class options
231
231
  # 2. Get non_cached_fields and fetch cache_fields
232
232
  # 3. Merge the two hashes using adapter_instance#fragment_cache
233
- def fetch_attributes_fragment(adapter_instance)
233
+ # rubocop:disable Metrics/AbcSize
234
+ def fetch_attributes_fragment(adapter_instance, cached_attributes = {})
234
235
  serializer_class._cache_options ||= {}
235
236
  serializer_class._cache_options[:key] = serializer_class._cache_key if serializer_class._cache_key
236
237
  fields = serializer_class.fragmented_attributes
@@ -243,15 +244,17 @@ module ActiveModel
243
244
  cached_fields = fields[:cached].dup
244
245
  key = cache_key(adapter_instance)
245
246
  cached_hash =
246
- serializer_class.cache_store.fetch(key, serializer_class._cache_options) do
247
- hash = attributes(cached_fields, true)
248
- include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys)
249
- hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance)
247
+ cached_attributes.fetch(key) do
248
+ serializer_class.cache_store.fetch(key, serializer_class._cache_options) do
249
+ hash = attributes(cached_fields, true)
250
+ include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys)
251
+ hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance)
252
+ end
250
253
  end
251
-
252
254
  # Merge both results
253
255
  adapter_instance.fragment_cache(cached_hash, non_cached_hash)
254
256
  end
257
+ # rubocop:enable Metrics/AbcSize
255
258
 
256
259
  def cache_key(adapter_instance)
257
260
  return @cache_key if defined?(@cache_key)
@@ -1,10 +1,14 @@
1
- class ActiveModel::Serializer::ErrorSerializer < ActiveModel::Serializer
2
- # @return [Hash<field_name,Array<error_message>>]
3
- def as_json
4
- object.errors.messages
5
- end
1
+ module ActiveModel
2
+ class Serializer
3
+ class ErrorSerializer < ActiveModel::Serializer
4
+ # @return [Hash<field_name,Array<error_message>>]
5
+ def as_json
6
+ object.errors.messages
7
+ end
6
8
 
7
- def success?
8
- false
9
+ def success?
10
+ false
11
+ end
12
+ end
9
13
  end
10
14
  end
@@ -1,27 +1,32 @@
1
1
  require 'active_model/serializer/error_serializer'
2
- class ActiveModel::Serializer::ErrorsSerializer
3
- include Enumerable
4
- delegate :each, to: :@serializers
5
- attr_reader :object, :root
6
2
 
7
- def initialize(resources, options = {})
8
- @root = options[:root]
9
- @object = resources
10
- @serializers = resources.map do |resource|
11
- serializer_class = options.fetch(:serializer) { ActiveModel::Serializer::ErrorSerializer }
12
- serializer_class.new(resource, options.except(:serializer))
13
- end
14
- end
3
+ module ActiveModel
4
+ class Serializer
5
+ class ErrorsSerializer
6
+ include Enumerable
7
+ delegate :each, to: :@serializers
8
+ attr_reader :object, :root
15
9
 
16
- def success?
17
- false
18
- end
10
+ def initialize(resources, options = {})
11
+ @root = options[:root]
12
+ @object = resources
13
+ @serializers = resources.map do |resource|
14
+ serializer_class = options.fetch(:serializer) { ActiveModel::Serializer::ErrorSerializer }
15
+ serializer_class.new(resource, options.except(:serializer))
16
+ end
17
+ end
19
18
 
20
- def json_key
21
- nil
22
- end
19
+ def success?
20
+ false
21
+ end
23
22
 
24
- protected
23
+ def json_key
24
+ nil
25
+ end
25
26
 
26
- attr_reader :serializers
27
+ protected
28
+
29
+ attr_reader :serializers
30
+ end
31
+ end
27
32
  end