Skip to content

Commit 6445930

Browse files
authored
Merge pull request #597 from affinity/moberegger/optimize_key_formatter
Optimize key formatter
2 parents 06f8eb9 + e0d60fd commit 6445930

File tree

4 files changed

+36
-35
lines changed

4 files changed

+36
-35
lines changed

lib/jbuilder.rb

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ class Jbuilder
1414
@@ignore_nil = false
1515
@@deep_format_keys = false
1616

17-
def initialize(options = {})
17+
def initialize(
18+
key_formatter: @@key_formatter,
19+
ignore_nil: @@ignore_nil,
20+
deep_format_keys: @@deep_format_keys,
21+
&block
22+
)
1823
@attributes = {}
24+
@key_formatter = key_formatter
25+
@ignore_nil = ignore_nil
26+
@deep_format_keys = deep_format_keys
1927

20-
@key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
21-
@ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
22-
@deep_format_keys = options.fetch(:deep_format_keys, @@deep_format_keys)
23-
24-
yield self if ::Kernel.block_given?
28+
yield self if block
2529
end
2630

2731
# Yields a builder and automatically turns the result into a JSON string
@@ -102,13 +106,13 @@ def method_missing(*args, &block)
102106
#
103107
# { "_first_name": "David" }
104108
#
105-
def key_format!(*args)
106-
@key_formatter = KeyFormatter.new(*args)
109+
def key_format!(...)
110+
@key_formatter = KeyFormatter.new(...)
107111
end
108112

109113
# Same as the instance method key_format! except sets the default.
110-
def self.key_format(*args)
111-
@@key_formatter = KeyFormatter.new(*args)
114+
def self.key_format(...)
115+
@@key_formatter = KeyFormatter.new(...)
112116
end
113117

114118
# If you want to skip adding nil values to your JSON hash. This is useful

lib/jbuilder/jbuilder_template.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ class << self
1212

1313
self.template_lookup_options = { handlers: [:jbuilder] }
1414

15-
def initialize(context, *args)
15+
def initialize(context, options = nil)
1616
@context = context
1717
@cached_root = nil
18-
super(*args)
18+
19+
options.nil? ? super() : super(**options)
1920
end
2021

2122
# Generates JSON using the template specified with the `:partial` option. For example, the code below will render

lib/jbuilder/key_formatter.rb

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,30 @@
11
# frozen_string_literal: true
22

33
require 'jbuilder/jbuilder'
4-
require 'active_support/core_ext/array'
54

65
class Jbuilder
76
class KeyFormatter
8-
def initialize(*args)
9-
@format = {}
10-
@cache = {}
11-
12-
options = args.extract_options!
13-
args.each do |name|
14-
@format[name] = []
15-
end
16-
options.each do |name, parameters|
17-
@format[name] = parameters
18-
end
19-
end
20-
21-
def initialize_copy(original)
7+
def initialize(*formats, **formats_with_options)
8+
@mutex = Mutex.new
9+
@formats = formats
10+
@formats_with_options = formats_with_options
2211
@cache = {}
2312
end
2413

2514
def format(key)
26-
@cache[key] ||= @format.inject(key.to_s) do |result, args|
27-
func, args = args
28-
if ::Proc === func
29-
func.call result, *args
30-
else
31-
result.send func, *args
15+
@mutex.synchronize do
16+
@cache[key] ||= begin
17+
value = key.is_a?(Symbol) ? key.name : key.to_s
18+
19+
@formats.each do |func|
20+
value = func.is_a?(Proc) ? func.call(value) : value.send(func)
21+
end
22+
23+
@formats_with_options.each do |func, params|
24+
value = func.is_a?(Proc) ? func.call(value, *params) : value.send(func, *params)
25+
end
26+
27+
value
3228
end
3329
end
3430
end

test/jbuilder_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -784,12 +784,12 @@ class JbuilderTest < ActiveSupport::TestCase
784784
assert_equal ['camelStyle'], result.keys
785785
end
786786

787-
test 'do not use default key formatter directly' do
787+
test 'use default key formatter when configured' do
788788
Jbuilder.key_format
789789
jbuild{ |json| json.key 'value' }
790790
formatter = Jbuilder.send(:class_variable_get, '@@key_formatter')
791791
cache = formatter.instance_variable_get('@cache')
792-
assert_empty cache
792+
assert_includes cache, :key
793793
end
794794

795795
test 'ignore_nil! without a parameter' do

0 commit comments

Comments
 (0)