jsoncache 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 451ecce81c2292abf00ea4b993b08ac32236b592
4
- data.tar.gz: 10f0b235b42b7b291db910eeee69d25f29687fc9
3
+ metadata.gz: 0b08ecd6e9c4902d08b774a84fd5eafc668fe297
4
+ data.tar.gz: 289211918f40306b69f94a26025b028802ca81d2
5
5
  SHA512:
6
- metadata.gz: 9002060bd1ef998f9ffbb8ed10243d024ea9da6ca9407cbe10cdc3da3f966514a074a1b8cc0a91334c53c3a54275bf26a4c702e964a05078a0e3deed28423daa
7
- data.tar.gz: e6814adf6f6d8fba88c676c6eaa6dcacf64a85690cad8f21db0154e319bcc7fbe9bb7db89fd3cd1066fa2e3d75d93bb12f26832bc4fdfb9b1df429edb1cce019
6
+ metadata.gz: 265fda72b840aac9515f4efaad4425b67b047ac0db604d5355d583741b9393efaf4eeeb506122a17227447db9a8c40ef644d180c03f6c4ed9b67aee8e200120a
7
+ data.tar.gz: c3908949c26d986c26842374a2b3bb64e60a8232cc9abd517d120044d0985ac09599befbb2662fe682630b3b3f327d585dac78839f1bc1c9648bd96059bf0c9e
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Derek Stride
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # JSONCache [![Build Status](https://travis-ci.org/DerekStride/jsoncache.svg?branch=dynamic-caching-based-on-arguments)](https://travis-ci.org/DerekStride/jsoncache)
2
+
3
+ A simple JSON Cache for use with HTTP APIs
4
+
5
+ ## Instructions
6
+
7
+ ```ruby
8
+ require 'jsoncache'
9
+ Class A
10
+ extend JSONCache
11
+
12
+ def expensive_method(args)
13
+ # code
14
+ end
15
+
16
+ cache :expensive_method, expiry: 300
17
+ end
18
+ ```
19
+
20
+ The cache method will the existing method and provide it with caching to the local filesystem. You can set a TTL (time to live) for the cache by setting the `expiry` value in seconds.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ task default: :spec
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.fail_on_error = false
8
+ end
data/lib/jsoncache.rb CHANGED
@@ -1,159 +1,18 @@
1
- require 'json'
2
- require 'pp'
1
+ require 'jsoncache/filecache'
3
2
 
4
3
  # JSONCache is a simple interface to cache JSON based API calls
5
4
  #
6
5
  # Author:: Derek Stride (mailto:djgstride@gmail.com)
7
6
  # License:: MIT
8
- #
9
- # This module provides an easy to use class method +cache+ which caches json
10
- # in a key-value fashion to the filesystem in /tmp/jsoncache.
11
7
  module JSONCache
12
- extend self
13
-
14
- # Retrieves cached data for the specified key and caches the data provided
15
- # if the cache isn't valid. Specify a code block after the method call that
16
- # returns a hash and it will be cached.
17
- #
18
- # ==== Parameters
19
- #
20
- # +key+:: +String+ The key in which to check for cached data.
21
- # +options+:: +Hash+ A hash of the parameters to use when caching.
22
- #
23
- # ==== Options
24
- #
25
- # Accepted options
26
- #
27
- # +:symbolize+:: +Boolean+ Symbolize keys while parsing JSON.
28
- # +:cache_directory+:: +String+ The folder name in /tmp to use as the cache.
29
- # +:expiry+:: +Fixnum+ The validity time of the cache in seconds.
30
- #
31
- # ==== Examples
32
- #
33
- # def get_response(uri)
34
- # JSONCache.cache(uri_to_key(uri), expiry: 120) do
35
- # query_some_json_api(uri)
36
- # end
37
- # end
38
- def cache(key, options = {})
39
- options = defaults.merge(options)
40
- return retrieve_cache(key, options) if cached?(key, options)
41
- result = yield
42
- cache_file(key, result, options)
43
- result
44
- end
45
-
46
- private
47
-
48
- ########################################################################
49
- # Core Caching
50
- ########################################################################
51
-
52
- # Determine whether a file is cached and healthy
53
- #
54
- # ==== Parameters
55
- #
56
- # +key+:: +String+ The key in which to check for cached data.
57
- # +options+:: +Hash+ A hash of the parameters to use when caching.
58
- def cached?(key, options = {})
59
- options = defaults.merge(options)
60
- timestamp = timestamp_from_key(key, options[:cache_directory])
61
- expiry = options[:expiry]
62
- if timestamp.zero?
63
- false
64
- elsif expiry.zero?
65
- true
66
- else
67
- (Time.now.to_i - timestamp) < expiry
8
+ def cache(method, options = {})
9
+ original = "__uncached_#{method}__"
10
+ ([Class, Module].include?(self.class) ? self : self.class).class_eval do
11
+ alias_method original, method
12
+ private original
13
+ define_method(method) do |*args|
14
+ JSONCache::FileCache.cache(*args, options) { send(original, *args) }
15
+ end
68
16
  end
69
17
  end
70
-
71
- # Cache the result from the uri
72
- #
73
- # ==== Parameters
74
- #
75
- # +key+:: +String+ The key in which to check for cached data.
76
- # +data+:: +Hash+ The data to cache.
77
- # +options+:: +Hash+ A hash of the parameters to use when caching.
78
- def cache_file(key, data, options = {})
79
- options = defaults.merge(options)
80
- begin
81
- content = JSON.generate(data)
82
- rescue
83
- return
84
- end
85
-
86
- cache_path = cache_dir(options[:cache_directory])
87
- existing_file = filename_from_key(key, options[:cache_directory])
88
- last_path = "#{cache_path}/#{existing_file}"
89
-
90
- File.delete(last_path) if existing_file && File.exist?(last_path)
91
- File.write(
92
- "#{cache_path}/#{key}#{Time.now.to_i}.json",
93
- content)
94
- end
95
-
96
- # Retrieves a cached value from a key
97
- #
98
- # ==== Parameters
99
- #
100
- # +key+:: +String+ The key in which to check for cached data.
101
- # +options+:: +Hash+ A hash of the parameters to use when caching.
102
- def retrieve_cache(key, options = {})
103
- options = defaults.merge(options)
104
- directory = options[:cache_directory]
105
- filename = filename_from_key(key, directory)
106
- return nil if filename.nil?
107
- JSON.parse(
108
- File.read("#{cache_dir(directory)}/#{filename}"),
109
- symbolize_names: options[:symbolize])
110
- end
111
-
112
- ########################################################################
113
- # Helpers
114
- ########################################################################
115
-
116
- # Create, if necessary, and return a cache directory
117
- #
118
- # ==== Parameters
119
- #
120
- # +directory+:: +String+ The name of the cache directory.
121
- def cache_dir(directory)
122
- directory ||= defaults[:cache_directory]
123
- cache_path = File.join('/tmp', directory)
124
- Dir.mkdir(cache_path) unless Dir.exist?(cache_path)
125
- cache_path
126
- end
127
-
128
- # Gets an existing file from a uri if it exists
129
- #
130
- # ==== Parameters
131
- #
132
- # +key+:: +String+ The key in which to check for cached data.
133
- # +directory+:: +String+ The name of the cache directory.
134
- def filename_from_key(key, directory)
135
- Dir.foreach(cache_dir(directory)) do |filename|
136
- next unless filename.include?(key)
137
- return filename
138
- end
139
- end
140
-
141
- # Extracts a timestamp from an existing file
142
- #
143
- # ==== Parameters
144
- #
145
- # +key+:: +String+ The key in which to check for cached data.
146
- # +directory+:: +String+ The name of the cache directory.
147
- def timestamp_from_key(key, directory)
148
- path = filename_from_key(key, directory)
149
- return 0 if path.nil?
150
- path.slice(/#{key}.*/)
151
- .gsub(/^#{key}/, '')
152
- .chomp('.json')
153
- .to_i
154
- end
155
-
156
- def defaults
157
- { symbolize: false, cache_directory: 'jsoncache', expiry: 0 }
158
- end
159
18
  end
@@ -0,0 +1,147 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+
4
+ module JSONCache
5
+ # This module provides an easy to use class method +cache+ which caches json
6
+ # in a key-value fashion to the filesystem in /tmp/jsoncache.
7
+ module FileCache
8
+ extend self
9
+
10
+ CACHE_DIR = '/tmp/jsoncache'.freeze
11
+
12
+ # Retrieves cached data for the specified key and caches the data provided
13
+ # if the cache isn't valid. Specify a code block after the method call that
14
+ # returns a hash and it will be cached.
15
+ #
16
+ # ==== Parameters
17
+ #
18
+ # +key+:: +String+ The key in which to check for cached data.
19
+ # +options+:: +Hash+ A hash of the parameters to use when caching.
20
+ #
21
+ # ==== Options
22
+ #
23
+ # Accepted options
24
+ #
25
+ # +:symbolize+:: +Boolean+ Symbolize keys while parsing JSON.
26
+ # +:cache_directory+:: +String+ The folder name in /tmp to use as the cache.
27
+ # +:expiry+:: +Fixnum+ The validity time of the cache in seconds.
28
+ #
29
+ # ==== Examples
30
+ #
31
+ # def get_response(uri)
32
+ # JSONCache.cache(uri_to_key(uri), expiry: 120) do
33
+ # query_some_json_api(uri)
34
+ # end
35
+ # end
36
+ def cache(*key, expiry: 0)
37
+ normalized_key = normalize(key)
38
+ return retrieve_cache(normalized_key) if cached?(normalized_key, expiry)
39
+ result = yield
40
+ cache_file(normalized_key, result)
41
+ result
42
+ end
43
+
44
+ private
45
+
46
+ ########################################################################
47
+ # Core Caching
48
+ ########################################################################
49
+
50
+ # Determine whether a file is cached and healthy
51
+ #
52
+ # ==== Parameters
53
+ #
54
+ # +key+:: +String+ The key in which to check for cached data.
55
+ # +options+:: +Hash+ A hash of the parameters to use when caching.
56
+ def cached?(key, expiry)
57
+ timestamp = timestamp_from_key(key)
58
+ if timestamp.zero?
59
+ false
60
+ elsif expiry.zero?
61
+ true
62
+ else
63
+ (Time.now.to_i - timestamp) < expiry
64
+ end
65
+ end
66
+
67
+ # Cache the result from the uri
68
+ #
69
+ # ==== Parameters
70
+ #
71
+ # +key+:: +String+ The key in which to check for cached data.
72
+ # +data+:: +Hash+ The data to cache.
73
+ # +options+:: +Hash+ A hash of the parameters to use when caching.
74
+ def cache_file(key, data)
75
+ begin
76
+ content = JSON.generate(data)
77
+ rescue
78
+ return
79
+ end
80
+
81
+ existing_file = filename_from_key(key)
82
+ last_path = "#{cache_dir}/#{existing_file}"
83
+
84
+ File.delete(last_path) if existing_file && File.exist?(last_path)
85
+ File.write("#{cache_dir}/#{key}#{Time.now.to_i}.json", content)
86
+ end
87
+
88
+ # Retrieves a cached value from a key
89
+ #
90
+ # ==== Parameters
91
+ #
92
+ # +key+:: +String+ The key in which to check for cached data.
93
+ # +options+:: +Hash+ A hash of the parameters to use when caching.
94
+ def retrieve_cache(key)
95
+ filename = filename_from_key(key)
96
+ return nil if filename.nil?
97
+ JSON.parse(File.read("#{cache_dir}/#{filename}"), symbolize_names: true)
98
+ end
99
+
100
+ ########################################################################
101
+ # Helpers
102
+ ########################################################################
103
+
104
+ # Create, if necessary, and return a cache directory
105
+ #
106
+ # ==== Parameters
107
+ #
108
+ # +directory+:: +String+ The name of the cache directory.
109
+ def cache_dir
110
+ FileUtils.mkdir_p(CACHE_DIR) unless Dir.exist?(CACHE_DIR)
111
+ CACHE_DIR
112
+ end
113
+
114
+ # Gets an existing file from a uri if it exists
115
+ #
116
+ # ==== Parameters
117
+ #
118
+ # +key+:: +String+ The key in which to check for cached data.
119
+ # +directory+:: +String+ The name of the cache directory.
120
+ def filename_from_key(key)
121
+ key = 'jsoncache' if key.empty?
122
+ Dir.foreach(cache_dir) do |filename|
123
+ next unless filename.include?(key)
124
+ return filename
125
+ end
126
+ end
127
+
128
+ # Extracts a timestamp from an existing file
129
+ #
130
+ # ==== Parameters
131
+ #
132
+ # +key+:: +String+ The key in which to check for cached data.
133
+ # +directory+:: +String+ The name of the cache directory.
134
+ def timestamp_from_key(key)
135
+ path = filename_from_key(key)
136
+ return 0 if path.nil?
137
+ path.slice(/#{key}.*/)
138
+ .gsub(/^#{key}/, '')
139
+ .chomp('.json')
140
+ .to_i
141
+ end
142
+
143
+ def normalize(key)
144
+ key.to_s.delete('{}()[]<>."\'=+:\/?~`!@#$%^&*|;, ')
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'jsoncache'
3
+
4
+ describe JSONCache::FileCache do
5
+ before :all do
6
+ @key = 'match1234567890'
7
+ @sample_data = { hello: 'world' }
8
+ end
9
+
10
+ describe '#cache' do
11
+ include FakeFS::SpecHelpers
12
+
13
+ context 'data not cached' do
14
+ it 'should yield control if there is no valid cache' do
15
+ expect { |b| JSONCache::FileCache.cache(@key, &b) }.to(
16
+ yield_control.once)
17
+ end
18
+ it 'should yield without args' do
19
+ expect { |b| JSONCache::FileCache.cache(@key, &b) }.not_to(
20
+ yield_with_args)
21
+ end
22
+ it 'should create a cache' do
23
+ expect(File.exist?(JSONCache::FileCache::CACHE_DIR)).to be false
24
+ JSONCache::FileCache.cache(@key) { @sample_data }
25
+ expect(File.exist?(JSONCache::FileCache::CACHE_DIR)).to be true
26
+ end
27
+ end
28
+
29
+ context 'data cached' do
30
+ before :each do
31
+ @cached_data = JSONCache::FileCache.cache(@key) { @sample_data }
32
+ end
33
+
34
+ it 'should not yield control' do
35
+ expect { |b| JSONCache::FileCache.cache(@key, &b) }.not_to yield_control
36
+ end
37
+ it 'should return the data from the block if no cache exists' do
38
+ expect(@cached_data).to eq @sample_data
39
+ end
40
+ it 'should return the old data if the cache is valid' do
41
+ new_data = { seeya: 'later' }
42
+ valid_cache_data = JSONCache::FileCache.cache(@key) { new_data }
43
+ expect(valid_cache_data).to eq @cached_data
44
+ end
45
+ it 'should return the new data if the cache is invalid' do
46
+ new_data = { seeya: 'later' }
47
+ invalid_cache_data = JSONCache::FileCache.cache(@key, expiry: -1) { new_data }
48
+ expect(invalid_cache_data).to eq new_data
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'pp'
3
+ require_relative '../lib/jsoncache'
4
+
5
+ # j
6
+ class JSONCacheTest
7
+ extend JSONCache
8
+
9
+ def perform(json = nil)
10
+ json
11
+ end
12
+
13
+ def expired(json = nil)
14
+ json
15
+ end
16
+
17
+ cache :perform
18
+ cache :expired, expiry: -1
19
+ end
20
+
21
+ describe JSONCacheTest do
22
+ before :all do
23
+ @uut = JSONCacheTest.new
24
+ @sample_data = { hello: 'world' }
25
+ end
26
+
27
+ describe '#perform' do
28
+ include FakeFS::SpecHelpers
29
+
30
+ context 'data not cached' do
31
+ it 'should create a cache' do
32
+ expect(File.exist?(JSONCache::FileCache::CACHE_DIR)).to be false
33
+ @uut.perform
34
+ expect(File.exist?(JSONCache::FileCache::CACHE_DIR)).to be true
35
+ end
36
+ it 'should create a cache based on the arguments' do
37
+ expect(File.exist?(JSONCache::FileCache::CACHE_DIR)).to be false
38
+ @uut.perform(@sample_data)
39
+ expect(File.exist?(JSONCache::FileCache::CACHE_DIR)).to be true
40
+ end
41
+ end
42
+
43
+ context 'data cached' do
44
+ before :each do
45
+ @cached_data = @uut.perform(@sample_data)
46
+ @key = JSONCache::FileCache.send(:normalize, @sample_data)
47
+ end
48
+
49
+ it 'should read from the cache' do
50
+ expect(@uut.perform(@sample_data)).to eq @cached_data
51
+ end
52
+ it 'should return the old data if the cache is valid' do
53
+ expect(@uut.perform(@key)).to eq @cached_data
54
+ end
55
+ it 'should return the new data if the cache is invalid' do
56
+ expect(@uut.expired(@key)).not_to eq @cached_data
57
+ expect(@uut.expired(@key)).to eq @key
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,98 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ require 'fakefs/spec_helpers'
20
+ RSpec.configure do |config|
21
+ # rspec-expectations config goes here. You can use an alternate
22
+ # assertion/expectation library such as wrong or the stdlib/minitest
23
+ # assertions if you prefer.
24
+ config.expect_with :rspec do |expectations|
25
+ # This option will default to `true` in RSpec 4. It makes the `description`
26
+ # and `failure_message` of custom matchers include text for helper methods
27
+ # defined using `chain`, e.g.:
28
+ # be_bigger_than(2).and_smaller_than(4).description
29
+ # # => "be bigger than 2 and smaller than 4"
30
+ # ...rather than:
31
+ # # => "be bigger than 2"
32
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33
+ config.order = :random
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # The settings below are suggested to provide a good initial experience
46
+ # with RSpec, but feel free to customize to your heart's content.
47
+ =begin
48
+ # These two settings work together to allow you to limit a spec run
49
+ # to individual examples or groups you care about by tagging them with
50
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
51
+ # get run.
52
+ config.filter_run :focus
53
+ config.run_all_when_everything_filtered = true
54
+
55
+ # Allows RSpec to persist some state between runs in order to support
56
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
57
+ # you configure your source control system to ignore this file.
58
+ config.example_status_persistence_file_path = "spec/examples.txt"
59
+
60
+ # Limits the available syntax to the non-monkey patched syntax that is
61
+ # recommended. For more details, see:
62
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
63
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
64
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
65
+ config.disable_monkey_patching!
66
+
67
+ # This setting enables warnings. It's recommended, but in some cases may
68
+ # be too noisy due to issues in dependencies.
69
+ config.warnings = true
70
+
71
+ # Many RSpec users commonly either run the entire suite or an individual
72
+ # file, and it's useful to allow more verbose output when running an
73
+ # individual spec file.
74
+ if config.files_to_run.one?
75
+ # Use the documentation formatter for detailed output,
76
+ # unless a formatter has already been configured
77
+ # (e.g. via a command-line flag).
78
+ config.default_formatter = 'doc'
79
+ end
80
+
81
+ # Print the 10 slowest examples and example groups at the
82
+ # end of the spec run, to help surface which specs are running
83
+ # particularly slow.
84
+ config.profile_examples = 10
85
+
86
+ # Run specs in random order to surface order dependencies. If you find an
87
+ # order dependency and want to debug it, you can fix the order by providing
88
+ # the seed, which is printed after each run.
89
+ # --seed 1234
90
+ config.order = :random
91
+
92
+ # Seed global randomization in this process using the `--seed` CLI option.
93
+ # Setting this allows you to use `--seed` to deterministically reproduce
94
+ # test failures related to randomization by passing the same `--seed` value
95
+ # as the one that triggered the failure.
96
+ Kernel.srand config.seed
97
+ =end
98
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsoncache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Stride
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-05 00:00:00.000000000 Z
11
+ date: 2016-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -30,7 +30,14 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
+ - LICENSE
34
+ - README.md
35
+ - Rakefile
33
36
  - lib/jsoncache.rb
37
+ - lib/jsoncache/filecache.rb
38
+ - spec/filecache_spec.rb
39
+ - spec/jsoncache_spec.rb
40
+ - spec/spec_helper.rb
34
41
  homepage: https://github.com/DerekStride/jsoncache
35
42
  licenses:
36
43
  - MIT
@@ -51,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
58
  version: '0'
52
59
  requirements: []
53
60
  rubyforge_project:
54
- rubygems_version: 2.4.5.1
61
+ rubygems_version: 2.6.4
55
62
  signing_key:
56
63
  specification_version: 4
57
64
  summary: Simple JSON Caching