active_model_serializers 0.10.0.rc2 → 0.10.0.rc3

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +82 -0
  4. data/.rubocop_todo.yml +315 -0
  5. data/.simplecov +99 -0
  6. data/.travis.yml +8 -0
  7. data/CHANGELOG.md +9 -3
  8. data/Gemfile +39 -8
  9. data/README.md +55 -31
  10. data/Rakefile +29 -2
  11. data/active_model_serializers.gemspec +37 -13
  12. data/appveyor.yml +25 -0
  13. data/docs/README.md +29 -0
  14. data/docs/general/adapters.md +110 -0
  15. data/docs/general/configuration_options.md +11 -0
  16. data/docs/general/getting_started.md +73 -0
  17. data/docs/howto/add_pagination_links.md +112 -0
  18. data/docs/howto/add_root_key.md +51 -0
  19. data/docs/howto/outside_controller_use.md +42 -0
  20. data/lib/action_controller/serialization.rb +24 -33
  21. data/lib/active_model/serializable_resource.rb +70 -0
  22. data/lib/active_model/serializer.rb +50 -131
  23. data/lib/active_model/serializer/adapter.rb +84 -21
  24. data/lib/active_model/serializer/adapter/flatten_json.rb +9 -9
  25. data/lib/active_model/serializer/adapter/fragment_cache.rb +10 -13
  26. data/lib/active_model/serializer/adapter/json.rb +25 -28
  27. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +2 -12
  28. data/lib/active_model/serializer/adapter/json_api.rb +100 -98
  29. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +4 -14
  30. data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +50 -0
  31. data/lib/active_model/serializer/adapter/null.rb +2 -8
  32. data/lib/active_model/serializer/array_serializer.rb +22 -17
  33. data/lib/active_model/serializer/association.rb +20 -0
  34. data/lib/active_model/serializer/associations.rb +97 -0
  35. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  36. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  37. data/lib/active_model/serializer/configuration.rb +1 -0
  38. data/lib/active_model/serializer/fieldset.rb +7 -7
  39. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  40. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  41. data/lib/active_model/serializer/lint.rb +129 -0
  42. data/lib/active_model/serializer/railtie.rb +7 -0
  43. data/lib/active_model/serializer/reflection.rb +74 -0
  44. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  45. data/lib/active_model/serializer/utils.rb +35 -0
  46. data/lib/active_model/serializer/version.rb +1 -1
  47. data/lib/active_model_serializers.rb +28 -14
  48. data/lib/generators/serializer/serializer_generator.rb +7 -7
  49. data/lib/generators/serializer/templates/{serializer.rb → serializer.rb.erb} +2 -2
  50. data/lib/tasks/rubocop.rake +0 -0
  51. data/test/action_controller/adapter_selector_test.rb +3 -3
  52. data/test/action_controller/explicit_serializer_test.rb +9 -9
  53. data/test/action_controller/json_api/linked_test.rb +179 -0
  54. data/test/action_controller/json_api/pagination_test.rb +116 -0
  55. data/test/action_controller/serialization_scope_name_test.rb +10 -6
  56. data/test/action_controller/serialization_test.rb +149 -112
  57. data/test/active_record_test.rb +9 -0
  58. data/test/adapter/fragment_cache_test.rb +11 -1
  59. data/test/adapter/json/belongs_to_test.rb +4 -5
  60. data/test/adapter/json/collection_test.rb +30 -21
  61. data/test/adapter/json/has_many_test.rb +20 -9
  62. data/test/adapter/json_api/belongs_to_test.rb +38 -38
  63. data/test/adapter/json_api/collection_test.rb +22 -23
  64. data/test/adapter/json_api/has_many_embed_ids_test.rb +2 -2
  65. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +4 -4
  66. data/test/adapter/json_api/has_many_test.rb +54 -19
  67. data/test/adapter/json_api/has_one_test.rb +28 -8
  68. data/test/adapter/json_api/json_api_test.rb +37 -0
  69. data/test/adapter/json_api/linked_test.rb +75 -75
  70. data/test/adapter/json_api/pagination_links_test.rb +115 -0
  71. data/test/adapter/json_api/resource_type_config_test.rb +59 -0
  72. data/test/adapter/json_test.rb +18 -5
  73. data/test/adapter_test.rb +10 -11
  74. data/test/array_serializer_test.rb +63 -5
  75. data/test/capture_warnings.rb +65 -0
  76. data/test/fixtures/active_record.rb +56 -0
  77. data/test/fixtures/poro.rb +60 -29
  78. data/test/generators/scaffold_controller_generator_test.rb +1 -2
  79. data/test/generators/serializer_generator_test.rb +17 -12
  80. data/test/lint_test.rb +37 -0
  81. data/test/logger_test.rb +18 -0
  82. data/test/poro_test.rb +9 -0
  83. data/test/serializable_resource_test.rb +27 -0
  84. data/test/serializers/adapter_for_test.rb +123 -3
  85. data/test/serializers/association_macros_test.rb +36 -0
  86. data/test/serializers/associations_test.rb +70 -47
  87. data/test/serializers/attribute_test.rb +28 -4
  88. data/test/serializers/attributes_test.rb +8 -14
  89. data/test/serializers/cache_test.rb +58 -31
  90. data/test/serializers/fieldset_test.rb +3 -4
  91. data/test/serializers/meta_test.rb +42 -28
  92. data/test/serializers/root_test.rb +21 -0
  93. data/test/serializers/serializer_for_test.rb +1 -1
  94. data/test/support/rails_app.rb +21 -0
  95. data/test/support/serialization_testing.rb +13 -0
  96. data/test/support/simplecov.rb +6 -0
  97. data/test/support/stream_capture.rb +50 -0
  98. data/test/support/test_case.rb +5 -0
  99. data/test/test_helper.rb +41 -29
  100. data/test/utils/include_args_to_hash_test.rb +79 -0
  101. metadata +123 -17
  102. data/test/action_controller/json_api_linked_test.rb +0 -179
  103. data/test/action_controller/rescue_from_test.rb +0 -32
  104. data/test/serializers/urls_test.rb +0 -26
@@ -0,0 +1,70 @@
1
+ require 'set'
2
+ module ActiveModel
3
+ class SerializableResource
4
+ ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter])
5
+
6
+ # Primary interface to composing a resource with a serializer and adapter.
7
+ # @return the serializable_resource, ready for #as_json/#to_json/#serializable_hash.
8
+ def initialize(resource, options = {})
9
+ @resource = resource
10
+ @adapter_opts, @serializer_opts =
11
+ options.partition { |k, _| ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
12
+ end
13
+
14
+ delegate :serializable_hash, :as_json, :to_json, to: :adapter
15
+
16
+ def serialization_scope=(scope)
17
+ serializer_opts[:scope] = scope
18
+ end
19
+
20
+ def serialization_scope
21
+ serializer_opts[:scope]
22
+ end
23
+
24
+ def serialization_scope_name=(scope_name)
25
+ serializer_opts[:scope_name] = scope_name
26
+ end
27
+
28
+ def adapter
29
+ @adapter ||= ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)
30
+ end
31
+ alias_method :adapter_instance, :adapter
32
+
33
+ def serializer_instance
34
+ @serializer_instance ||= serializer.new(resource, serializer_opts)
35
+ end
36
+
37
+ # Get serializer either explicitly :serializer or implicitly from resource
38
+ # Remove :serializer key from serializer_opts
39
+ # Replace :serializer key with :each_serializer if present
40
+ def serializer
41
+ @serializer ||=
42
+ begin
43
+ @serializer = serializer_opts.delete(:serializer)
44
+ @serializer ||= ActiveModel::Serializer.serializer_for(resource)
45
+
46
+ if serializer_opts.key?(:each_serializer)
47
+ serializer_opts[:serializer] = serializer_opts.delete(:each_serializer)
48
+ end
49
+ @serializer
50
+ end
51
+ end
52
+ alias_method :serializer_class, :serializer
53
+
54
+ # True when no explicit adapter given, or explicit appear is truthy (non-nil)
55
+ # False when explicit adapter is falsy (nil or false)
56
+ def use_adapter?
57
+ !(adapter_opts.key?(:adapter) && !adapter_opts[:adapter])
58
+ end
59
+
60
+ def serializer?
61
+ use_adapter? && !!(serializer)
62
+ end
63
+
64
+ private
65
+
66
+ ActiveModelSerializers.silence_warnings do
67
+ attr_reader :resource, :adapter_opts, :serializer_opts
68
+ end
69
+ end
70
+ end
@@ -3,16 +3,35 @@ require 'thread_safe'
3
3
  module ActiveModel
4
4
  class Serializer
5
5
  extend ActiveSupport::Autoload
6
+
6
7
  autoload :Configuration
7
8
  autoload :ArraySerializer
8
9
  autoload :Adapter
10
+ autoload :Lint
11
+ autoload :Associations
12
+ autoload :Fieldset
13
+ autoload :Utils
9
14
  include Configuration
15
+ include Associations
16
+
17
+ # Matches
18
+ # "c:/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb:1:in `<top (required)>'"
19
+ # AND
20
+ # "/c/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb:1:in `<top (required)>'"
21
+ # AS
22
+ # c/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb
23
+ CALLER_FILE = /
24
+ \A # start of string
25
+ \S+ # one or more non-spaces
26
+ (?= # stop previous match when
27
+ :\d+ # a colon is followed by one or more digits
28
+ :in # followed by a colon followed by in
29
+ )
30
+ /x
10
31
 
11
32
  class << self
12
33
  attr_accessor :_attributes
13
34
  attr_accessor :_attributes_keys
14
- attr_accessor :_associations
15
- attr_accessor :_urls
16
35
  attr_accessor :_cache
17
36
  attr_accessor :_fragmented
18
37
  attr_accessor :_cache_key
@@ -23,12 +42,10 @@ module ActiveModel
23
42
  end
24
43
 
25
44
  def self.inherited(base)
26
- base._attributes = self._attributes.try(:dup) || []
45
+ base._attributes = self._attributes.try(:dup) || []
27
46
  base._attributes_keys = self._attributes_keys.try(:dup) || {}
28
- base._associations = self._associations.try(:dup) || {}
29
- base._urls = []
30
- serializer_file = File.open(caller.first[/^[^:]+/])
31
- base._cache_digest = Digest::MD5.hexdigest(serializer_file.read)
47
+ base._cache_digest = digest_caller_file(caller.first)
48
+ super
32
49
  end
33
50
 
34
51
  def self.attributes(*attrs)
@@ -45,11 +62,14 @@ module ActiveModel
45
62
 
46
63
  def self.attribute(attr, options = {})
47
64
  key = options.fetch(:key, attr)
48
- @_attributes_keys[attr] = {key: key} if key != attr
65
+ @_attributes_keys[attr] = { key: key } if key != attr
49
66
  @_attributes << key unless @_attributes.include?(key)
50
- define_method key do
51
- object.read_attribute_for_serialization(attr)
52
- end unless method_defined?(key) || _fragmented.respond_to?(attr)
67
+
68
+ ActiveModelSerializers.silence_warnings do
69
+ define_method key do
70
+ object.read_attribute_for_serialization(attr)
71
+ end unless (key != :id && method_defined?(key)) || _fragmented.respond_to?(attr)
72
+ end
53
73
  end
54
74
 
55
75
  def self.fragmented(serializer)
@@ -58,91 +78,26 @@ module ActiveModel
58
78
 
59
79
  # Enables a serializer to be automatically cached
60
80
  def self.cache(options = {})
61
- @_cache = ActionController::Base.cache_store if Rails.configuration.action_controller.perform_caching
62
- @_cache_key = options.delete(:key)
63
- @_cache_only = options.delete(:only)
64
- @_cache_except = options.delete(:except)
81
+ @_cache = ActionController::Base.cache_store if Rails.configuration.action_controller.perform_caching
82
+ @_cache_key = options.delete(:key)
83
+ @_cache_only = options.delete(:only)
84
+ @_cache_except = options.delete(:except)
65
85
  @_cache_options = (options.empty?) ? nil : options
66
86
  end
67
87
 
68
- # Defines an association in the object should be rendered.
69
- #
70
- # The serializer object should implement the association name
71
- # as a method which should return an array when invoked. If a method
72
- # with the association name does not exist, the association name is
73
- # dispatched to the serialized object.
74
- def self.has_many(*attrs)
75
- associate(:has_many, attrs)
76
- end
77
-
78
- # Defines an association in the object that should be rendered.
79
- #
80
- # The serializer object should implement the association name
81
- # as a method which should return an object when invoked. If a method
82
- # with the association name does not exist, the association name is
83
- # dispatched to the serialized object.
84
- def self.belongs_to(*attrs)
85
- associate(:belongs_to, attrs)
86
- end
87
-
88
- # Defines an association in the object should be rendered.
89
- #
90
- # The serializer object should implement the association name
91
- # as a method which should return an object when invoked. If a method
92
- # with the association name does not exist, the association name is
93
- # dispatched to the serialized object.
94
- def self.has_one(*attrs)
95
- associate(:has_one, attrs)
96
- end
97
-
98
- def self.associate(type, attrs) #:nodoc:
99
- options = attrs.extract_options!
100
- self._associations = _associations.dup
101
-
102
- attrs.each do |attr|
103
- unless method_defined?(attr)
104
- define_method attr do
105
- object.send attr
106
- end
107
- end
108
-
109
- self._associations[attr] = {type: type, association_options: options}
110
- end
111
- end
112
-
113
- def self.url(attr)
114
- @_urls.push attr
115
- end
116
-
117
- def self.urls(*attrs)
118
- @_urls.concat attrs
119
- end
120
-
121
88
  def self.serializer_for(resource, options = {})
122
89
  if resource.respond_to?(:serializer_class)
123
90
  resource.serializer_class
124
91
  elsif resource.respond_to?(:to_ary)
125
92
  config.array_serializer
126
93
  else
127
- options
128
- .fetch(:association_options, {})
129
- .fetch(:serializer, get_serializer_for(resource.class))
94
+ options.fetch(:serializer, get_serializer_for(resource.class))
130
95
  end
131
96
  end
132
97
 
98
+ # @see ActiveModel::Serializer::Adapter.lookup
133
99
  def self.adapter
134
- adapter_class = case config.adapter
135
- when Symbol
136
- ActiveModel::Serializer::Adapter.adapter_class(config.adapter)
137
- when Class
138
- config.adapter
139
- end
140
- unless adapter_class
141
- valid_adapters = Adapter.constants.map { |klass| ":#{klass.to_s.downcase}" }
142
- raise ArgumentError, "Unknown adapter: #{config.adapter}. Valid adapters are: #{valid_adapters}"
143
- end
144
-
145
- adapter_class
100
+ ActiveModel::Serializer::Adapter.lookup(config.adapter)
146
101
  end
147
102
 
148
103
  def self.root_name
@@ -152,12 +107,12 @@ module ActiveModel
152
107
  attr_accessor :object, :root, :meta, :meta_key, :scope
153
108
 
154
109
  def initialize(object, options = {})
155
- @object = object
156
- @options = options
157
- @root = options[:root]
158
- @meta = options[:meta]
159
- @meta_key = options[:meta_key]
160
- @scope = options[:scope]
110
+ @object = object
111
+ @options = options
112
+ @root = options[:root]
113
+ @meta = options[:meta]
114
+ @meta_key = options[:meta_key]
115
+ @scope = options[:scope]
161
116
 
162
117
  scope_name = options[:scope_name]
163
118
  if scope_name && !respond_to?(scope_name)
@@ -168,15 +123,7 @@ module ActiveModel
168
123
  end
169
124
 
170
125
  def json_key
171
- self.class.root_name
172
- end
173
-
174
- def id
175
- object.id if object
176
- end
177
-
178
- def type
179
- object.class.model_name.plural
126
+ @root || object.class.model_name.to_s.underscore
180
127
  end
181
128
 
182
129
  def attributes(options = {})
@@ -187,8 +134,6 @@ module ActiveModel
187
134
  self.class._attributes.dup
188
135
  end
189
136
 
190
- attributes += options[:required_fields] if options[:required_fields]
191
-
192
137
  attributes.each_with_object({}) do |name, hash|
193
138
  unless self.class._fragmented
194
139
  hash[name] = send(name)
@@ -198,40 +143,15 @@ module ActiveModel
198
143
  end
199
144
  end
200
145
 
201
- def each_association(&block)
202
- self.class._associations.dup.each do |name, association_options|
203
- next unless object
204
- association_value = send(name)
205
-
206
- serializer_class = ActiveModel::Serializer.serializer_for(association_value, association_options)
207
-
208
- if serializer_class
209
- serializer = serializer_class.new(
210
- association_value,
211
- options.except(:serializer).merge(serializer_from_options(association_options))
212
- )
213
- elsif !association_value.nil? && !association_value.instance_of?(Object)
214
- association_options[:association_options][:virtual_value] = association_value
215
- end
216
-
217
- if block_given?
218
- block.call(name, serializer, association_options[:association_options])
219
- end
220
- end
221
- end
222
-
223
- def serializer_from_options(options)
224
- opts = {}
225
- serializer = options.fetch(:association_options, {}).fetch(:serializer, nil)
226
- opts[:serializer] = serializer if serializer
227
- opts
228
- end
229
-
230
146
  def self.serializers_cache
231
147
  @serializers_cache ||= ThreadSafe::Cache.new
232
148
  end
233
149
 
234
- private
150
+ def self.digest_caller_file(caller_line)
151
+ serializer_file_path = caller_line[CALLER_FILE]
152
+ serializer_file_contents = IO.read(serializer_file_path)
153
+ Digest::MD5.hexdigest(serializer_file_contents)
154
+ end
235
155
 
236
156
  attr_reader :options
237
157
 
@@ -247,6 +167,5 @@ module ActiveModel
247
167
  end
248
168
  end
249
169
  end
250
-
251
170
  end
252
171
  end
@@ -1,13 +1,84 @@
1
- require 'active_model/serializer/adapter/fragment_cache'
2
-
3
1
  module ActiveModel
4
2
  class Serializer
5
3
  class Adapter
4
+ UnknownAdapterError = Class.new(ArgumentError)
5
+ ADAPTER_MAP = {}
6
+ private_constant :ADAPTER_MAP if defined?(private_constant)
6
7
  extend ActiveSupport::Autoload
8
+ autoload :FragmentCache
7
9
  autoload :Json
8
- autoload :FlattenJson
9
- autoload :Null
10
10
  autoload :JsonApi
11
+ autoload :Null
12
+ autoload :FlattenJson
13
+
14
+ def self.create(resource, options = {})
15
+ override = options.delete(:adapter)
16
+ klass = override ? adapter_class(override) : ActiveModel::Serializer.adapter
17
+ klass.new(resource, options)
18
+ end
19
+
20
+ # @see ActiveModel::Serializer::Adapter.lookup
21
+ def self.adapter_class(adapter)
22
+ ActiveModel::Serializer::Adapter.lookup(adapter)
23
+ end
24
+
25
+ # Only the Adapter class has these methods.
26
+ # None of the sublasses have them.
27
+ class << ActiveModel::Serializer::Adapter
28
+ # @return Hash<adapter_name, adapter_class>
29
+ def adapter_map
30
+ ADAPTER_MAP
31
+ end
32
+
33
+ # @return [Array<Symbol>] list of adapter names
34
+ def adapters
35
+ adapter_map.keys.sort
36
+ end
37
+
38
+ # Adds an adapter 'klass' with 'name' to the 'adapter_map'
39
+ # Names are stringified and underscored
40
+ # @param [Symbol, String] name of the registered adapter
41
+ # @param [Class] klass - adapter class itself
42
+ # @example
43
+ # AMS::Adapter.register(:my_adapter, MyAdapter)
44
+ def register(name, klass)
45
+ adapter_map.update(name.to_s.underscore => klass)
46
+ self
47
+ end
48
+
49
+ # @param adapter [String, Symbol, Class] name to fetch adapter by
50
+ # @return [ActiveModel::Serializer::Adapter] subclass of Adapter
51
+ # @raise [UnknownAdapterError]
52
+ def lookup(adapter)
53
+ # 1. return if is a class
54
+ return adapter if adapter.is_a?(Class)
55
+ adapter_name = adapter.to_s.underscore
56
+ # 2. return if registered
57
+ adapter_map.fetch(adapter_name) {
58
+ # 3. try to find adapter class from environment
59
+ adapter_class = find_by_name(adapter_name)
60
+ register(adapter_name, adapter_class)
61
+ adapter_class
62
+ }
63
+ rescue NameError, ArgumentError => e
64
+ failure_message =
65
+ "NameError: #{e.message}. Unknown adapter: #{adapter.inspect}. Valid adapters are: #{adapters}"
66
+ raise UnknownAdapterError, failure_message, e.backtrace
67
+ end
68
+
69
+ # @api private
70
+ def find_by_name(adapter_name)
71
+ adapter_name = adapter_name.to_s.classify.tr('API', 'Api')
72
+ ActiveModel::Serializer::Adapter.const_get(adapter_name.to_sym) or # rubocop:disable Style/AndOr
73
+ fail UnknownAdapterError
74
+ end
75
+ private :find_by_name
76
+ end
77
+
78
+ # Automatically register adapters when subclassing
79
+ def self.inherited(subclass)
80
+ ActiveModel::Serializer::Adapter.register(subclass.to_s.demodulize, subclass)
81
+ end
11
82
 
12
83
  attr_reader :serializer
13
84
 
@@ -16,33 +87,23 @@ module ActiveModel
16
87
  @options = options
17
88
  end
18
89
 
19
- def serializable_hash(options = {})
90
+ def serializable_hash(options = nil)
20
91
  raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.'
21
92
  end
22
93
 
23
- def as_json(options = {})
94
+ def as_json(options = nil)
24
95
  hash = serializable_hash(options)
25
- include_meta(hash) unless self.class == FlattenJson
96
+ include_meta(hash)
26
97
  hash
27
98
  end
28
99
 
29
- def self.create(resource, options = {})
30
- override = options.delete(:adapter)
31
- klass = override ? adapter_class(override) : ActiveModel::Serializer.adapter
32
- klass.new(resource, options)
33
- end
34
-
35
- def self.adapter_class(adapter)
36
- "ActiveModel::Serializer::Adapter::#{adapter.to_s.classify}".safe_constantize
37
- end
38
-
39
100
  def fragment_cache(*args)
40
101
  raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.'
41
102
  end
42
103
 
43
104
  private
44
105
 
45
- def cache_check(serializer)
106
+ def cache_check(serializer)
46
107
  @cached_serializer = serializer
47
108
  @klass = @cached_serializer.class
48
109
  if is_cached?
@@ -68,11 +129,13 @@ module ActiveModel
68
129
  parts = []
69
130
  parts << object_cache_key
70
131
  parts << @klass._cache_digest unless @klass._cache_options && @klass._cache_options[:skip_digest]
71
- parts.join("/")
132
+ parts.join('/')
72
133
  end
73
134
 
74
135
  def object_cache_key
75
- (@klass._cache_key) ? "#{@klass._cache_key}/#{@cached_serializer.object.id}-#{@cached_serializer.object.updated_at}" : @cached_serializer.object.cache_key
136
+ object_time_safe = @cached_serializer.object.updated_at
137
+ object_time_safe = object_time_safe.strftime('%Y%m%d%H%M%S%9N') if object_time_safe.respond_to?(:strftime)
138
+ (@klass._cache_key) ? "#{@klass._cache_key}/#{@cached_serializer.object.id}-#{object_time_safe}" : @cached_serializer.object.cache_key
76
139
  end
77
140
 
78
141
  def meta
@@ -80,7 +143,7 @@ module ActiveModel
80
143
  end
81
144
 
82
145
  def meta_key
83
- serializer.meta_key || "meta"
146
+ serializer.meta_key || 'meta'
84
147
  end
85
148
 
86
149
  def root