Skip to content

Commit fe1c787

Browse files
committed
Merge 00c54ba into 2e31a14
2 parents 2e31a14 + 00c54ba commit fe1c787

File tree

8 files changed

+109
-3
lines changed

8 files changed

+109
-3
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ def default_serializer_options
226226
end
227227
```
228228

229+
## Changing the Key Format
230+
231+
You can specify that serializers use the lower-camel key format at the config, class or instance level.
232+
233+
```ruby
234+
235+
ActiveModel::Serializer.setup do |config|
236+
config.key_format = :lower_camel
237+
end
238+
239+
class BlogLowerCamelSerializer < ActiveModel::Serializer
240+
format_keys :lower_camel
241+
end
242+
243+
BlogSerializer.new(object, key_format: :lower_camel)
244+
```
245+
229246
## Getting the old version
230247

231248
If you find that your project is already relying on the old rails to_json

lib/active_model/array_serializer.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ def initialize(object, options={})
2020
@meta = options[@meta_key]
2121
@each_serializer = options[:each_serializer]
2222
@resource_name = options[:resource_name]
23+
@key_format = options[:key_format]
2324
end
24-
attr_accessor :object, :scope, :root, :meta_key, :meta
25+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
2526

2627
def json_key
2728
if root.nil?
@@ -33,7 +34,7 @@ def json_key
3334

3435
def serializer_for(item)
3536
serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer
36-
serializer_class.new(item, scope: scope)
37+
serializer_class.new(item, scope: scope, key_format: key_format)
3738
end
3839

3940
def serializable_object

lib/active_model/serializer.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ def embed(type, options={})
3838
WARN
3939
end
4040

41+
def format_keys(format)
42+
@key_format = format
43+
end
44+
attr_reader :key_format
45+
4146
if RUBY_VERSION >= '2.0'
4247
def serializer_for(resource)
4348
if resource.respond_to?(:to_ary)
@@ -110,6 +115,7 @@ def initialize(object, options={})
110115
@wrap_in_array = options[:_wrap_in_array]
111116
@only = Array(options[:only]) if options[:only]
112117
@except = Array(options[:except]) if options[:except]
118+
@key_format = options[:key_format]
113119
end
114120
attr_accessor :object, :scope, :root, :meta_key, :meta
115121

@@ -190,10 +196,35 @@ def serialize_ids(association)
190196
end
191197
end
192198

199+
def key_format
200+
@key_format || self.class.key_format || CONFIG.key_format
201+
end
202+
203+
def format_key(key)
204+
if key_format == :lower_camel
205+
key.to_s.camelize(:lower)
206+
else
207+
key
208+
end
209+
end
210+
211+
def convert_keys(hash)
212+
Hash[hash.map do |k,v|
213+
key = if k.is_a?(Symbol)
214+
format_key(k).to_sym
215+
else
216+
format_key(k)
217+
end
218+
219+
[key ,v]
220+
end]
221+
end
222+
193223
def serializable_object(options={})
194224
return @wrap_in_array ? [] : nil if @object.nil?
195225
hash = attributes
196226
hash.merge! associations
227+
hash = convert_keys(hash) if key_format.present?
197228
@wrap_in_array ? [hash] : hash
198229
end
199230
alias_method :serializable_hash, :serializable_object

lib/active_model/serializer/associations.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def initialize(name, options={})
1515
@options = options
1616
self.embed = options.fetch(:embed) { CONFIG.embed }
1717
@embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
18+
@key_format = options.fetch(:key_format) { CONFIG.key_format }
1819
@embed_key = options[:embed_key] || :id
1920
@key = options[:key]
2021
@embedded_key = options[:root] || name
@@ -24,7 +25,7 @@ def initialize(name, options={})
2425
end
2526

2627
attr_reader :name, :embed_ids, :embed_objects
27-
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options
28+
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format
2829
alias embed_ids? embed_ids
2930
alias embed_objects? embed_objects
3031
alias embed_in_root? embed_in_root

test/fixtures/poro.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ def comments
3535
class Comment < Model
3636
end
3737

38+
class Blog < Model
39+
end
40+
3841
###
3942
## Serializers
4043
###
@@ -62,3 +65,11 @@ class PostSerializer < ActiveModel::Serializer
6265
class CommentSerializer < ActiveModel::Serializer
6366
attributes :content
6467
end
68+
69+
class BlogSerializer < ActiveModel::Serializer
70+
attributes :name, :display_name
71+
end
72+
73+
class BlogLowerCamelSerializer < BlogSerializer
74+
format_keys :lower_camel
75+
end
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require 'test_helper'
2+
3+
module ActiveModel
4+
class ArraySerializer
5+
class KeyFormatTest < Minitest::Test
6+
def test_array_serializer_pass_options_to_items_serializers
7+
array = [Blog.new({ name: 'Name 1', display_name: 'Display Name 1'}),
8+
Blog.new({ name: 'Name 2', display_name: 'Display Name 2'})]
9+
serializer = ArraySerializer.new(array, key_format: :lower_camel)
10+
11+
expected = [{ name: 'Name 1', displayName: 'Display Name 1' },
12+
{ name: 'Name 2', displayName: 'Display Name 2' }]
13+
14+
assert_equal expected, serializer.serializable_array
15+
end
16+
end
17+
end
18+
end

test/unit/active_model/serializer/config_test.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class ApplyConfigTest < Minitest::Test
6767
def test_apply_config_to_associations
6868
CONFIG.embed = :ids
6969
CONFIG.embed_in_root = true
70+
CONFIG.key_format = :lower_camel
7071

7172
association = PostSerializer._associations[:comments]
7273
old_association = association.dup
@@ -76,6 +77,7 @@ def test_apply_config_to_associations
7677
assert association.embed_ids?
7778
assert !association.embed_objects?
7879
assert association.embed_in_root
80+
assert_equal :lower_camel, association.key_format
7981
ensure
8082
PostSerializer._associations[:comments] = old_association
8183
CONFIG.clear
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'test_helper'
2+
3+
module ActiveModel
4+
class Serializer
5+
class KeyFormatTest < Minitest::Test
6+
def test_lower_camel_format_option
7+
object = Blog.new({ name: 'Name 1', display_name: 'Display Name 1'})
8+
serializer = BlogSerializer.new(object, key_format: :lower_camel)
9+
10+
expected = { name: 'Name 1', displayName: 'Display Name 1' }
11+
12+
assert_equal expected, serializer.serializable_object
13+
end
14+
15+
def test_lower_camel_format_serializer
16+
object = Blog.new({ name: 'Name 1', display_name: 'Display Name 1'})
17+
serializer = BlogLowerCamelSerializer.new(object)
18+
19+
expected = { name: 'Name 1', displayName: 'Display Name 1' }
20+
21+
assert_equal expected, serializer.serializable_object
22+
end
23+
end
24+
end
25+
end

0 commit comments

Comments
 (0)