active_model_serializers 0.10.0.rc2 → 0.10.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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