kartograph 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0295131c24571bb5b97074b8c6ddb293d6e6e5c5
4
- data.tar.gz: c54a19d0f60e9671b01f46dc7c3e22e9336f4a1d
3
+ metadata.gz: cd413914c014eb3f1127307accfe7415bd9cf5e0
4
+ data.tar.gz: 6f9f614581f8542da63cf5ed48253058608e37aa
5
5
  SHA512:
6
- metadata.gz: 1f9810e797d94884d70753280442945dd1c8a05fc956d0e545e81fed318fdf087468ad315b60ecc98a8bbd3967f8ad82a0234ace82b75ace8b1e9146f5e3c1d7
7
- data.tar.gz: 31cd1b4efc22648129ee836936bd90e42ee428ae351526784ae3e307d7148e473558a3982768b8d9137e530d08a50622525410a3d40b5912cc4f1615b587276f
6
+ metadata.gz: 0df0e80384d6964490b4bd1102dbccc597e21c2bfc0c60bad4d2326541845f86cc1ed15200db6f79a831f904dcb062366993cc441581718114ac79577e43fb93
7
+ data.tar.gz: 62da5885c11e5f6445e4d8132e91f70256b6a16966de26cbe35b2d38bb037b6e29a94fe7ab6bbe90d95e72fa1229de8d6a253a5b107279feff6432f30a2c327d
data/README.md CHANGED
@@ -173,6 +173,25 @@ end
173
173
 
174
174
  Now when JSON includes comments for a user, it will know how to map the comments using the provided Kartograph definition.
175
175
 
176
+ ---
177
+
178
+ ### Caching
179
+
180
+ Kartograph has the option to cache certain serializations, determined by the way you setup the key.
181
+
182
+ ```ruby
183
+ class UserMapping
184
+ include Kartograph::DSL
185
+
186
+ kartograph do
187
+ cache { Rails.cache } # As long as this respond to #fetch(key_name, options = {}, &block) it will work
188
+ cache_key { |object| object.cache_key }
189
+
190
+ end
191
+ end
192
+ end
193
+ ```
194
+
176
195
  ## Contributing
177
196
 
178
197
  1. Fork it ( https://github.com/digitaloceancloud/kartograph/fork )
data/lib/kartograph.rb CHANGED
@@ -11,4 +11,14 @@ module Kartograph
11
11
 
12
12
  autoload :Artist, 'kartograph/artist'
13
13
  autoload :Sculptor, 'kartograph/sculptor'
14
+
15
+ class << self
16
+ attr_accessor :default_dumper
17
+ attr_accessor :default_loader
18
+ attr_accessor :default_cache
19
+ attr_accessor :default_cache_key
20
+ end
21
+
22
+ self.default_dumper = JSON
23
+ self.default_loader = JSON
14
24
  end
@@ -12,9 +12,19 @@ module Kartograph
12
12
  end
13
13
 
14
14
  def draw(scope = nil)
15
+ if map.cache
16
+ cache_key = map.cache_key.call(object, scope)
17
+ map.cache.fetch(cache_key) { build_properties(scope) }
18
+ else
19
+ build_properties(scope)
20
+ end
21
+ end
22
+
23
+ def build_properties(scope)
15
24
  scoped_properties = scope ? properties.filter_by_scope(scope) : properties
16
25
  scoped_properties.each_with_object({}) do |property, mapped|
17
26
  raise ArgumentError, "#{object} does not respond to #{property.name}, so we can't map it" unless object.respond_to?(property.name)
27
+
18
28
  mapped[property.key] = property.value_for(object, scope)
19
29
  end
20
30
  end
@@ -15,13 +15,13 @@ module Kartograph
15
15
  @kartograph_map
16
16
  end
17
17
 
18
- def representation_for(scope, object, dumper = JSON)
18
+ def representation_for(scope, object, dumper = Kartograph.default_dumper)
19
19
  drawed = Artist.new(object, @kartograph_map).draw(scope)
20
20
 
21
21
  dumper.dump(prepend_root_key(scope, :singular, drawed))
22
22
  end
23
23
 
24
- def represent_collection_for(scope, objects, dumper = JSON)
24
+ def represent_collection_for(scope, objects, dumper = Kartograph.default_dumper)
25
25
  drawed_objects = objects.map do |object|
26
26
  Artist.new(object, @kartograph_map).draw(scope)
27
27
  end
@@ -29,7 +29,7 @@ module Kartograph
29
29
  dumper.dump(prepend_root_key(scope, :plural, drawed_objects))
30
30
  end
31
31
 
32
- def extract_single(content, scope, loader = JSON)
32
+ def extract_single(content, scope, loader = Kartograph.default_loader)
33
33
  loaded = loader.load(content)
34
34
 
35
35
  retrieve_root_key(scope, :singular) do |root_key|
@@ -40,7 +40,7 @@ module Kartograph
40
40
  Sculptor.new(loaded, @kartograph_map).sculpt(scope)
41
41
  end
42
42
 
43
- def extract_collection(content, scope, loader = JSON)
43
+ def extract_collection(content, scope, loader = Kartograph.default_loader)
44
44
  loaded = loader.load(content)
45
45
 
46
46
  retrieve_root_key(scope, :plural) do |root_key|
@@ -29,6 +29,16 @@ module Kartograph
29
29
  root_keys << RootKey.new(options)
30
30
  end
31
31
 
32
+ def cache(object = nil)
33
+ @cache = object unless object.nil?
34
+ @cache.nil? ? Kartograph.default_cache : @cache
35
+ end
36
+
37
+ def cache_key(&calculator)
38
+ @cache_calculator = calculator if block_given?
39
+ @cache_calculator.nil? ? Kartograph.default_cache_key : @cache_calculator
40
+ end
41
+
32
42
  def root_key_for(scope, type)
33
43
  return unless %i(singular plural).include?(type)
34
44
 
@@ -48,6 +58,9 @@ module Kartograph
48
58
  self.root_keys.each do |rk|
49
59
  map.root_keys << rk
50
60
  end
61
+
62
+ map.cache self.cache
63
+ map.cache_key &self.cache_key if self.cache_key
51
64
  end
52
65
  end
53
66
 
@@ -1,4 +1,4 @@
1
1
  module Kartograph
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
4
4
 
@@ -78,5 +78,37 @@ describe Kartograph::Artist do
78
78
  end
79
79
  end
80
80
  end
81
+
82
+ context "with caching enabled" do
83
+ let(:cacher) { double('cacher', fetch: { foo: 'cached-value' }) }
84
+ let(:object) { double('object', foo: 'bar', cache_key: 'test-cache-key') }
85
+
86
+ it "uses the cache fetch for values" do
87
+ map.cache(cacher)
88
+ map.cache_key { |obj, scope| obj.cache_key }
89
+ map.property :foo
90
+
91
+ artist = Kartograph::Artist.new(object, map)
92
+ masterpiece = artist.draw
93
+
94
+ expect(masterpiece).to eq(cacher.fetch)
95
+
96
+ expect(cacher).to have_received(:fetch).with('test-cache-key')
97
+ end
98
+
99
+ it "uses the cache key for the object and scope" do
100
+ called = double(call: 'my-cache')
101
+
102
+ map.cache(cacher)
103
+ map.cache_key { |obj, scope| called.call(obj, scope) }
104
+
105
+ map.property :foo, scopes: [:read]
106
+
107
+ artist = Kartograph::Artist.new(object, map)
108
+ masterpiece = artist.draw(:read)
109
+
110
+ expect(called).to have_received(:call).with(object, :read)
111
+ end
112
+ end
81
113
  end
82
114
  end
@@ -68,6 +68,10 @@ describe Kartograph::Map do
68
68
  map.mapping mapped_class
69
69
  map.root_key singular: 'woot', plural: 'woots', scopes: [:read]
70
70
 
71
+ cache_key = Proc.new {}
72
+ map.cache 'hello'
73
+ map.cache_key &cache_key
74
+
71
75
  new_map = map.dup
72
76
 
73
77
  expect(new_map.properties[0]).to_not be(prop1)
@@ -79,6 +83,54 @@ describe Kartograph::Map do
79
83
 
80
84
  expect(new_map.mapping).to eq(mapped_class)
81
85
  expect(new_map.root_keys).to eq(map.root_keys)
86
+
87
+ expect(new_map.cache).to eq(map.cache)
88
+ expect(new_map.cache_key).to eq(cache_key)
89
+ end
90
+ end
91
+
92
+ describe '#cache' do
93
+ it "stores the caching method" do
94
+ cacher = double
95
+ map.cache cacher
96
+
97
+ expect(map.cache).to be(cacher)
98
+ end
99
+
100
+ it 'returns the kartograph cache if set' do
101
+ cacher = double('cache')
102
+ Kartograph.default_cache = cacher
103
+
104
+ expect(map.cache).to be(cacher)
105
+ end
106
+
107
+ it 'goes straight to the object if cache is overridden with false' do
108
+ cacher = double('cache')
109
+ Kartograph.default_cache = cacher
110
+
111
+ property = Kartograph::Property.new(:bunk) do
112
+ cache false
113
+ end
114
+
115
+ map.properties << property
116
+
117
+ expect(property.map.cache).to be(false)
118
+ end
119
+ end
120
+
121
+ describe '#cache_key' do
122
+ it 'stores the cache key block' do
123
+ cache_key = Proc.new {}
124
+ map.cache_key(&cache_key)
125
+
126
+ expect(map.cache_key).to be(cache_key)
127
+ end
128
+
129
+ it 'returns the kartograph cache_key if set' do
130
+ cache_key = double('cache key')
131
+ Kartograph.default_cache_key = cache_key
132
+
133
+ expect(map.cache_key).to be(cache_key)
82
134
  end
83
135
  end
84
136
 
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@ Dir['./spec/support/**/*.rb'].each {|f| load f }
5
5
  RSpec.configure do |config|
6
6
  # The settings below are suggested to provide a good initial experience
7
7
  # with RSpec, but feel free to customize to your heart's content.
8
- =begin
8
+
9
9
  # These two settings work together to allow you to limit a spec run
10
10
  # to individual examples or groups you care about by tagging them with
11
11
  # `:focus` metadata. When nothing is tagged with `:focus`, all examples
@@ -13,6 +13,15 @@ RSpec.configure do |config|
13
13
  config.filter_run :focus
14
14
  config.run_all_when_everything_filtered = true
15
15
 
16
+ config.after(:each) do
17
+ Kartograph.default_dumper = JSON
18
+ Kartograph.default_loader = JSON
19
+ Kartograph.default_cache = nil
20
+ Kartograph.default_cache_key = nil
21
+ end
22
+
23
+ =begin
24
+
16
25
  # Many RSpec users commonly either run the entire suite or an individual
17
26
  # file, and it's useful to allow more verbose output when running an
18
27
  # individual spec file.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kartograph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Ross
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-14 00:00:00.000000000 Z
11
+ date: 2014-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler