more_core_extensions 3.3.0 → 3.4.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: 8445d02cce0bc6bc1cfc1554bd6db773e335c2f8
4
- data.tar.gz: 010cb3f4eb19a5d6c36a7593e77d65012b48e8c8
3
+ metadata.gz: 413a7851ecc9b2985a2186985d125319d91d7260
4
+ data.tar.gz: d8b660b117dca1de5e71a21184e75485942c8406
5
5
  SHA512:
6
- metadata.gz: 4731d3a3029b3aa664031f4c794ce22f57da5c4718dd6c6bd4810b0a98a112d19028c3d7ca1400c64568f3505d6e6798dd76b4eec59e106bbedba7637b894a84
7
- data.tar.gz: f0660e800d33a9d89c02a84e21825b7ed0ff7712594844dc3b5159dc1d0dbf960023a15005221501aabe5aa0255d9986c2e9f8e64497e1ecd673c25841b63489
6
+ metadata.gz: ec665edef944f6aab6555c17bdb2c6e2ead4a0c782a107b45c096d3fd89a4aad81cf5fa54c9921a24048a70bdbcb3197d7e83ac4f48f0a672f1bfd6a7bebbf4d
7
+ data.tar.gz: baba9a0b258fc9097bb6759ca4af9d753a8fbc8e0475b9ef50676e464247df8bb5252fd8f92cf0abb23b72c52c884704c106d847625bfbf9ac5e9442f67b0d35
@@ -0,0 +1,4 @@
1
+ GlobalVars:
2
+ AllowedVariables:
3
+ - $cache_with_timeout
4
+ - $cache_with_timeout_lock
@@ -4,6 +4,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [3.4.0] - 2017-08-11
8
+ ### Added
9
+ - Added Module#cache_with_timeout [[#51](https://github.com/ManageIQ/more_core_extensions/pull/51)]
10
+
11
+ ### Changed
12
+ - Performance improvements to store_path [[#54](https://github.com/ManageIQ/more_core_extensions/pull/54)]
13
+ and fetch_path [[#55](https://github.com/ManageIQ/more_core_extensions/pull/55)]
14
+
7
15
  ## [3.3.0] - 2017-07-21
8
16
  ### Added
9
17
  - Added Symbol#to_i [[#49](https://github.com/ManageIQ/more_core_extensions/pull/49)]
@@ -45,7 +53,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
45
53
  - Upgraded to RSpec 3 [[#16](https://github.com/ManageIQ/more_core_extensions/pull/16)]
46
54
  - Added the Change Log!
47
55
 
48
- [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v3.3.0...HEAD
56
+ [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v3.4.0...HEAD
57
+ [3.4.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.3.0...v3.4.0
49
58
  [3.3.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.2.0...v3.3.0
50
59
  [3.2.0]: https://github.com/ManageIQ/more_core_extensions/compare/v3.1.1...v3.2.0
51
60
  [3.1.1]: https://github.com/ManageIQ/more_core_extensions/compare/v3.1.0...v3.1.1
data/README.md CHANGED
@@ -57,6 +57,9 @@ MoreCoreExtensions are a set of core extensions beyond those provided by ActiveS
57
57
 
58
58
  #### Module
59
59
 
60
+ * core_ext/module/cache_with_timeout.rb
61
+ * `#cache_with_timeout` - Creates singleton methods that cache the results of the given block, but only for a short amount of time.
62
+ * `.clear_all_cache_with_timeout` - Globally clears all cached values across all classes.
60
63
  * core_ext/module/namespace.rb
61
64
  * `#namespace` - Returns an Array with the namespace to the current Module
62
65
 
@@ -1 +1,2 @@
1
+ require 'more_core_extensions/core_ext/module/cache_with_timeout'
1
2
  require 'more_core_extensions/core_ext/module/namespace'
@@ -0,0 +1,101 @@
1
+ require 'sync'
2
+
3
+ $cache_with_timeout = {}
4
+ $cache_with_timeout_lock = Sync.new
5
+
6
+ module MoreCoreExtensions
7
+ module CacheWithTimeout
8
+ # cache_with_timeout creates singleton methods that cache the
9
+ # results of the given block, but only for a short amount of time.
10
+ # If the method is called again after time has passed, then the
11
+ # cache is cleared and the block is reevaluated. Note that the
12
+ # cache is only cleared on the next invocation after the time has
13
+ # passed, so if the block retains references to large objects,
14
+ # they will never be garbage collected if the method is never
15
+ # called again.
16
+ #
17
+ # The methods created are
18
+ # - `method`
19
+ # - `#{method}_clear_cache` - Will clear the cached value on demand
20
+ # - `#{method}_cached?` - Says whether or not there is a value cached
21
+ #
22
+ # Example:
23
+ # class Foo
24
+ # cache_with_timeout(:expensive_operation) do
25
+ # sleep 100
26
+ # rand(100)
27
+ # end
28
+ # end
29
+ #
30
+ # Foo.expensive_operation # => 42
31
+ # Foo.expensive_operation # => 42
32
+ # # ... wait 5+ minutes ...
33
+ # Foo.expensive_operation # => 18
34
+ #
35
+ # @param [String|Symbol] method The name of the method to create.
36
+ # @param [Integer] timeout The number of seconds after which the cache is
37
+ # cleared (defaults to: 300 (5 minutes))
38
+ # @returns [Symbol] The name of the method created.
39
+ def cache_with_timeout(method, timeout = nil, &block)
40
+ raise "no block given" if block.nil?
41
+ raise ArgumentError, "method must be a Symbol" unless method.respond_to?(:to_sym)
42
+
43
+ key = "#{name}.#{method}".to_sym
44
+
45
+ $cache_with_timeout_lock.synchronize(:EX) do
46
+ $cache_with_timeout[key] = {}
47
+ end
48
+
49
+ define_singleton_method(method) do |*args|
50
+ force_reload = args.first
51
+ return $cache_with_timeout_lock.synchronize(:EX) do
52
+ cache = $cache_with_timeout[key]
53
+
54
+ old_timeout = cache[:timeout]
55
+ cache.clear if force_reload || (old_timeout && Time.now.utc > old_timeout)
56
+ break cache[:value] if cache.key?(:value)
57
+
58
+ new_timeout = timeout || 300 # 5 minutes
59
+ new_timeout = new_timeout.call if new_timeout.kind_of?(Proc)
60
+ new_timeout = Time.now.utc + new_timeout
61
+ new_value = block.call
62
+
63
+ cache[:timeout] = new_timeout
64
+ cache[:value] = new_value
65
+ end
66
+ end
67
+
68
+ define_singleton_method("#{method}_clear_cache") do |*_args|
69
+ $cache_with_timeout_lock.synchronize(:EX) do
70
+ $cache_with_timeout[key].clear
71
+ end
72
+ end
73
+
74
+ define_singleton_method("#{method}_cached?") do |*_args|
75
+ $cache_with_timeout_lock.synchronize(:EX) do
76
+ !$cache_with_timeout[key].empty?
77
+ end
78
+ end
79
+
80
+ method.to_sym
81
+ end
82
+
83
+ module ClassMethods
84
+ # Globally clears all cached values across all classes. This is
85
+ # mostly useful for testing to avoid test contamination.
86
+ #
87
+ # Example:
88
+ # RSpec.configure do |c|
89
+ # c.after { Module.clear_all_cache_with_timeout }
90
+ # end
91
+ def clear_all_cache_with_timeout
92
+ $cache_with_timeout_lock.synchronize(:EX) do
93
+ $cache_with_timeout.each_value(&:clear)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ Module.send(:include, MoreCoreExtensions::CacheWithTimeout)
101
+ Module.send(:extend, MoreCoreExtensions::CacheWithTimeout::ClassMethods)
@@ -26,13 +26,17 @@ module MoreCoreExtensions
26
26
  args = args.first if args.length == 1 && args.first.kind_of?(Array)
27
27
  raise ArgumentError, "must pass at least one key" if args.empty?
28
28
 
29
- key = args.first
30
- raise ArgumentError, "must be a number" if self.kind_of?(Array) && !key.kind_of?(Numeric)
29
+ result = self
30
+ args.each_with_index do |key, i|
31
+ raise ArgumentError, "must be a number" if result.kind_of?(Array) && !key.kind_of?(Numeric)
31
32
 
32
- child = self[key]
33
- return child if args.length == 1
34
- return nil unless child.respond_to?(:fetch_path)
35
- return child.fetch_path(args[1..-1])
33
+ result = result[key]
34
+ if !result.respond_to?(:fetch_path) && (i + 1) != args.size
35
+ result = nil
36
+ break
37
+ end
38
+ end
39
+ result
36
40
  end
37
41
 
38
42
  #
@@ -62,21 +66,25 @@ module MoreCoreExtensions
62
66
  def store_path(*args)
63
67
  raise ArgumentError, "must pass at least one key, and a value" if args.length < 2
64
68
  value = args.pop
65
- args = args.first if args.length == 1 && args.first.kind_of?(Array)
69
+ child = self
70
+ key = args.first
66
71
 
67
- key = args.first
68
- raise ArgumentError, "must be a number" if self.kind_of?(Array) && !key.kind_of?(Numeric)
72
+ if args.length > 1 || args.first.kind_of?(Array)
73
+ keys = args.first.kind_of?(Array) ? args.first : args
74
+ keys.each_with_index do |cur_key, i|
75
+ raise ArgumentError, "must be a number" if child.kind_of?(Array) && !cur_key.kind_of?(Numeric)
76
+ key = cur_key # keep track of this for value assignment later
77
+ break if i + 1 == keys.size
69
78
 
70
- if args.length == 1
71
- self[key] = value
72
- else
73
- child = self[key]
74
- unless child.respond_to?(:store_path)
75
- self[key] = self.class.new
76
- child = self[key]
79
+ unless child[cur_key].respond_to?(:store_path)
80
+ child[cur_key] = child.class.new
81
+ end
82
+
83
+ child = child[cur_key]
77
84
  end
78
- child.store_path(args[1..-1].push, value)
79
85
  end
86
+
87
+ child[key] = value
80
88
  end
81
89
 
82
90
  #
@@ -1,3 +1,3 @@
1
1
  module MoreCoreExtensions
2
- VERSION = "3.3.0".freeze
2
+ VERSION = "3.4.0".freeze
3
3
  end
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rake"
28
28
  spec.add_development_dependency "rspec", ">= 3.0"
29
29
  spec.add_development_dependency "simplecov"
30
+ spec.add_development_dependency "timecop"
30
31
 
31
32
  spec.add_runtime_dependency "activesupport"
32
33
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: more_core_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Frey
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-07-24 00:00:00.000000000 Z
12
+ date: 2017-08-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: timecop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
84
98
  - !ruby/object:Gem::Dependency
85
99
  name: activesupport
86
100
  requirement: !ruby/object:Gem::Requirement
@@ -133,6 +147,7 @@ files:
133
147
  - lib/more_core_extensions/core_ext/hash/nested.rb
134
148
  - lib/more_core_extensions/core_ext/hash/sorting.rb
135
149
  - lib/more_core_extensions/core_ext/module.rb
150
+ - lib/more_core_extensions/core_ext/module/cache_with_timeout.rb
136
151
  - lib/more_core_extensions/core_ext/module/namespace.rb
137
152
  - lib/more_core_extensions/core_ext/numeric.rb
138
153
  - lib/more_core_extensions/core_ext/numeric/clamp.rb
@@ -173,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
188
  version: '0'
174
189
  requirements: []
175
190
  rubyforge_project:
176
- rubygems_version: 2.5.2
191
+ rubygems_version: 2.6.11
177
192
  signing_key:
178
193
  specification_version: 4
179
194
  summary: MoreCoreExtensions are a set of core extensions beyond those provided by