Skip to content

Commit a3f14c3

Browse files
committed
Fix option caching issues
fix #123 fix #125
1 parent bcf433d commit a3f14c3

4 files changed

Lines changed: 44 additions & 29 deletions

File tree

lib/multi_json.rb

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ module MultiJson
55
include Options
66
extend self
77

8+
class << self
9+
def cached_options
10+
@cached_options || reset_cached_options!
11+
end
12+
13+
def reset_cached_options!
14+
@cached_options = {}
15+
end
16+
end
17+
818
class LoadError < StandardError
919
attr_reader :data
1020
def initialize(message='', backtrace=[], data='')
@@ -27,17 +37,7 @@ def default_options=(value)
2737
self.load_options = self.dump_options = value
2838
end
2939

30-
# cache busting
31-
%w(load_options= dump_options=).each do |method|
32-
define_method method do |*args|
33-
use current_adapter
34-
super(*args)
35-
end
36-
end
37-
38-
ALIASES = {
39-
'jrjackson' => :jr_jackson
40-
}
40+
ALIASES = { 'jrjackson' => :jr_jackson }
4141

4242
REQUIREMENT_MAP = [
4343
['oj', :oj],
@@ -95,9 +95,7 @@ def adapter
9595
# * <tt>:gson</tt> (JRuby only)
9696
# * <tt>:jr_jackson</tt> (JRuby only)
9797
def use(new_adapter)
98-
adapter = load_adapter(new_adapter)
99-
adapter.activate! if adapter.respond_to?(:activate!)
100-
@adapter = adapter
98+
@adapter = load_adapter(new_adapter)
10199
end
102100
alias adapter= use
103101
alias engine= use

lib/multi_json/adapter.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,34 @@ def defaults(action, value)
1515
end
1616
end
1717

18-
def activate!
19-
@load_options_cache = {}
20-
@dump_options_cache = {}
21-
instance.activate if instance.respond_to?(:activate)
22-
end
23-
2418
def load(string, options={})
25-
instance.load(string, collect_load_options(string, options).clone)
19+
instance.load(string, collect_load_options(options).clone)
2620
end
2721

2822
def dump(object, options={})
29-
instance.dump(object, collect_dump_options(object, options).clone)
23+
instance.dump(object, collect_dump_options(options).clone)
3024
end
3125

3226
protected
3327

34-
def collect_load_options(string, options)
35-
@load_options_cache[options] ||= collect_options(:load_options, options).merge(options)
28+
def collect_load_options(options)
29+
cache('load', options){ collect_options(:load_options, options).merge(options) }
3630
end
3731

38-
def collect_dump_options(object, options)
39-
@dump_options_cache[options] ||= collect_options(:dump_options, options).merge(options)
32+
def collect_dump_options(options)
33+
cache('dump', options){ collect_options(:dump_options, options).merge(options) }
4034
end
4135

4236
def collect_options(method, *args)
4337
global, local = *[MultiJson, self].map{ |r| r.send(method, *args) }
4438
local.merge(global)
4539
end
4640

41+
def cache(method, options)
42+
cache_key = [self, options].map(&:hash).join + method
43+
MultiJson.cached_options[cache_key] ||= yield
44+
end
45+
4746
end
4847
end
4948
end

lib/multi_json/options.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
module MultiJson
22
module Options
3-
attr_writer :load_options, :dump_options
3+
4+
def load_options=(options)
5+
MultiJson.reset_cached_options!
6+
@load_options = options
7+
end
8+
9+
def dump_options=(options)
10+
MultiJson.reset_cached_options!
11+
@dump_options = options
12+
end
413

514
def load_options(*args)
615
get_options :load_options, *args

spec/multi_json_spec.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,24 @@
5151
end
5252

5353
context 'caching' do
54-
before{ MultiJson.use :json_gem }
54+
before{ MultiJson.use adapter }
55+
let(:adapter){ MultiJson::Adapters::JsonGem }
5556
let(:json_string){ '{"abc":"def"}' }
5657

57-
it 'busts options caches on change' do
58+
it 'busts caches on global options change' do
5859
MultiJson.load_options = { :symbolize_keys => true }
5960
expect(MultiJson.load(json_string)).to eq(:abc => 'def')
6061
MultiJson.load_options = nil
6162
expect(MultiJson.load(json_string)).to eq('abc' => 'def')
6263
end
64+
65+
it 'busts caches on per-adapter options change' do
66+
adapter.load_options = { :symbolize_keys => true }
67+
expect(MultiJson.load(json_string)).to eq(:abc => 'def')
68+
adapter.load_options = nil
69+
expect(MultiJson.load(json_string)).to eq('abc' => 'def')
70+
end
71+
6372
end
6473

6574
it 'defaults to the best available gem' do

0 commit comments

Comments
 (0)