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
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