diff --git a/lib/jbuilder.rb b/lib/jbuilder.rb index b12624b..db2f25c 100644 --- a/lib/jbuilder.rb +++ b/lib/jbuilder.rb @@ -12,14 +12,18 @@ class Jbuilder @@ignore_nil = false @@deep_format_keys = false - def initialize(options = {}) + def initialize( + key_formatter: @@key_formatter, + ignore_nil: @@ignore_nil, + deep_format_keys: @@deep_format_keys, + &block + ) @attributes = {} + @key_formatter = key_formatter + @ignore_nil = ignore_nil + @deep_format_keys = deep_format_keys - @key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil} - @ignore_nil = options.fetch(:ignore_nil, @@ignore_nil) - @deep_format_keys = options.fetch(:deep_format_keys, @@deep_format_keys) - - yield self if ::Kernel.block_given? + yield self if block end # Yields a builder and automatically turns the result into a JSON string @@ -100,13 +104,13 @@ def method_missing(*args, &block) # # { "_first_name": "David" } # - def key_format!(*args) - @key_formatter = KeyFormatter.new(*args) + def key_format!(...) + @key_formatter = KeyFormatter.new(...) end # Same as the instance method key_format! except sets the default. - def self.key_format(*args) - @@key_formatter = KeyFormatter.new(*args) + def self.key_format(...) + @@key_formatter = KeyFormatter.new(...) end # If you want to skip adding nil values to your JSON hash. This is useful diff --git a/lib/jbuilder/jbuilder_template.rb b/lib/jbuilder/jbuilder_template.rb index 55f2d5f..2984aaf 100644 --- a/lib/jbuilder/jbuilder_template.rb +++ b/lib/jbuilder/jbuilder_template.rb @@ -10,10 +10,11 @@ class << self self.template_lookup_options = { handlers: [:jbuilder] } - def initialize(context, *args) + def initialize(context, options = nil) @context = context @cached_root = nil - super(*args) + + options.nil? ? super() : super(**options) end # Generates JSON using the template specified with the `:partial` option. For example, the code below will render diff --git a/lib/jbuilder/key_formatter.rb b/lib/jbuilder/key_formatter.rb index c9e7eca..2c0f1f9 100644 --- a/lib/jbuilder/key_formatter.rb +++ b/lib/jbuilder/key_formatter.rb @@ -1,32 +1,28 @@ require 'jbuilder/jbuilder' -require 'active_support/core_ext/array' class Jbuilder class KeyFormatter - def initialize(*args) - @format = {} - @cache = {} - - options = args.extract_options! - args.each do |name| - @format[name] = [] - end - options.each do |name, parameters| - @format[name] = parameters - end - end - - def initialize_copy(original) + def initialize(*formats, **formats_with_options) + @mutex = Mutex.new + @formats = formats + @formats_with_options = formats_with_options @cache = {} end def format(key) - @cache[key] ||= @format.inject(key.to_s) do |result, args| - func, args = args - if ::Proc === func - func.call result, *args - else - result.send func, *args + @mutex.synchronize do + @cache[key] ||= begin + value = key.is_a?(Symbol) ? key.name : key.to_s + + @formats.each do |func| + value = func.is_a?(Proc) ? func.call(value) : value.send(func) + end + + @formats_with_options.each do |func, params| + value = func.is_a?(Proc) ? func.call(value, *params) : value.send(func, *params) + end + + value end end end diff --git a/test/jbuilder_test.rb b/test/jbuilder_test.rb index 76569bb..4f2cbe2 100644 --- a/test/jbuilder_test.rb +++ b/test/jbuilder_test.rb @@ -784,12 +784,12 @@ class JbuilderTest < ActiveSupport::TestCase assert_equal ['camelStyle'], result.keys end - test 'do not use default key formatter directly' do + test 'use default key formatter when configured' do Jbuilder.key_format jbuild{ |json| json.key 'value' } formatter = Jbuilder.send(:class_variable_get, '@@key_formatter') cache = formatter.instance_variable_get('@cache') - assert_empty cache + assert_includes cache, :key end test 'ignore_nil! without a parameter' do