progress_tracker 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/lib/progress_tracker/base.rb +95 -0
- data/lib/progress_tracker/version.rb +3 -0
- data/lib/progress_tracker.rb +13 -0
- data/progress_tracker.gemspec +29 -0
- data/spec/progress_tracker_spec.rb +116 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: df21ecd837ae3df9bde25bb75176b76b74babba1
|
4
|
+
data.tar.gz: fdc09b64c60c0b47579458b6b665b65584cd0bea
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c21785f5a9253a41c869b221aae9e295b3a524ff2f5e2387d0b1285bad7cd10d4a158dd6c3e46162e6005b35af19c2c5d973963a96f81e737941cf03c7989d3b
|
7
|
+
data.tar.gz: 64c5f45f120e788bbe67ecda28f830d8a4cc0c8c884b934245d35af5e75339d0bc970e4276463df5145d5c8e81d8a26f01bd0013c38a70ab496238149a1aedad
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format documentation
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Dan Cheail <dan@undumb.com>
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# ProgressTracker
|
2
|
+
|
3
|
+
ProgressTracker is a very simple API for logging and retreiving the progress of
|
4
|
+
a given background task. It lets you track the progress / status of multiple
|
5
|
+
objects, and retrieve them as a single set.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'progress_tracker'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install progress_tracker
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Track objects associated with a simple name, or emable the user of a class / id pair
|
24
|
+
|
25
|
+
pt = ProgressTracker.new(:thing)
|
26
|
+
pt = ProgressTracker.new(:billing_cycle, id)
|
27
|
+
|
28
|
+
# Sane Defaults
|
29
|
+
pt = ProgressTracker.new(:foo, 10)
|
30
|
+
pt.to_hash # => { progress: 0, message: "" }
|
31
|
+
|
32
|
+
|
33
|
+
Update the progess / messages on the base object
|
34
|
+
|
35
|
+
pt.progress 50
|
36
|
+
pt.message "String"
|
37
|
+
pt.status "BAD"
|
38
|
+
|
39
|
+
Or, just chuck anything you want in there
|
40
|
+
|
41
|
+
pt.update progress: 50, message: "Strang.", status: "BAD", herpy: "derpy"
|
42
|
+
|
43
|
+
Alternatviely, track seperate, named sub-objects, again with name or class / id pair
|
44
|
+
|
45
|
+
pt.track :cycle
|
46
|
+
pt.track :bill, 10
|
47
|
+
pt.track :bill, 11
|
48
|
+
pt.track :bill, 13
|
49
|
+
|
50
|
+
# update progress percentage
|
51
|
+
pt.cycle.progress 34
|
52
|
+
pt.bill(34).progress 92
|
53
|
+
|
54
|
+
# update status message
|
55
|
+
pt.cycle.message "Message"
|
56
|
+
pt.bill(34).message "Message"
|
57
|
+
|
58
|
+
# or, update them both at the same time
|
59
|
+
pt.cycle.update progress: 14, message: "Message"
|
60
|
+
pt.bill(34).update progress: 14, message: "Message"
|
61
|
+
|
62
|
+
Then, in an new context, re-initialise and retreive a complete overview:
|
63
|
+
|
64
|
+
pt = ProgressTracker.new(:billing_cycle, id)
|
65
|
+
pt.to_hash # => {
|
66
|
+
_base: { progress: 19, message: "Message" },
|
67
|
+
cycle: { progress: 19, message: "Message" },
|
68
|
+
bill_10: { progress: 19, message: "Message" },
|
69
|
+
bill_11: { progress: 19, message: "Message" },
|
70
|
+
bill_13: { progress: 19, message: "Message" },
|
71
|
+
}
|
72
|
+
|
73
|
+
And easily convert it to JSON as needed:
|
74
|
+
|
75
|
+
pt.to_json
|
76
|
+
|
77
|
+
## Contributing
|
78
|
+
|
79
|
+
1. Fork it
|
80
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
81
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
82
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
83
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module ProgressTracker
|
2
|
+
class Base
|
3
|
+
|
4
|
+
# Enable the selection of a Redis connection
|
5
|
+
class << self
|
6
|
+
attr_accessor :redis_connection
|
7
|
+
end
|
8
|
+
|
9
|
+
# And default to using the established global var (yes, I know. Bad.)
|
10
|
+
@redis_connection = $redis
|
11
|
+
|
12
|
+
# Instance-level access to Redis (actually a Redis::Namespace)
|
13
|
+
attr_reader :redis, :base_key
|
14
|
+
|
15
|
+
# All sub-objects tracked with Base#track
|
16
|
+
attr_reader :tracked_object_keys
|
17
|
+
|
18
|
+
# The tracked object that this instance currently refers to
|
19
|
+
attr_accessor :current_tracked_object
|
20
|
+
|
21
|
+
# Just so we've always got values...
|
22
|
+
DEFAULTS = { progress: 0, message: "" }
|
23
|
+
|
24
|
+
def initialize(object_name, object_id = nil)
|
25
|
+
@base_key = _ck(object_name, object_id)
|
26
|
+
|
27
|
+
@redis = ::Redis::Namespace.new(@base_key, redis: ProgressTracker::Base.redis_connection)
|
28
|
+
|
29
|
+
# initialize or fetch our tracked object keys from Redis, ensuring we at least have _base present
|
30
|
+
@tracked_object_keys = Set.new(redis.smembers("tracked-object-keys").map(&:to_sym) << :_base)
|
31
|
+
|
32
|
+
@current_tracked_object = :_base
|
33
|
+
end
|
34
|
+
|
35
|
+
# Build a compound key and store it for future reference
|
36
|
+
def track(object_name, object_id = nil)
|
37
|
+
new_key = _ck(object_name, object_id)
|
38
|
+
|
39
|
+
redis.sadd "tracked-object-keys", new_key
|
40
|
+
tracked_object_keys << new_key
|
41
|
+
end
|
42
|
+
|
43
|
+
# grab all the keys related to this set from redis
|
44
|
+
def to_hash
|
45
|
+
tracked_object_keys.inject({}) do |hash, key|
|
46
|
+
hash.tap do |h|
|
47
|
+
h[key] = DEFAULTS.merge(redis.hgetall(key).symbolize_keys)
|
48
|
+
|
49
|
+
# Make sure :progress is always returned as an integer
|
50
|
+
h[key][:progress] = h[key][:progress].to_i
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# If a method is called that matches the name of a tracked object, return
|
57
|
+
# a new instance of self with the @current_tracked_object set
|
58
|
+
# to the correct key
|
59
|
+
def method_missing(meth, *args)
|
60
|
+
meth_key = _ck(meth, args.first)
|
61
|
+
|
62
|
+
if tracked_object_keys.include?(meth_key)
|
63
|
+
self.dup.tap do |t|
|
64
|
+
t.current_tracked_object = meth_key
|
65
|
+
end
|
66
|
+
else
|
67
|
+
raise NoMethodError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def update(hsh)
|
73
|
+
redis.hmset current_tracked_object, *hsh.to_a.flatten
|
74
|
+
end
|
75
|
+
|
76
|
+
def progress(value)
|
77
|
+
update progress: value.to_i
|
78
|
+
end
|
79
|
+
|
80
|
+
def message(msg)
|
81
|
+
update message: msg
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# build a compound key in the format (name_id)
|
87
|
+
def _ck(object_name, object_id = nil)
|
88
|
+
if object_id
|
89
|
+
:"#{object_name}_#{object_id}"
|
90
|
+
else
|
91
|
+
object_name.to_sym
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'progress_tracker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "progress_tracker"
|
8
|
+
spec.version = ProgressTracker::VERSION
|
9
|
+
spec.authors = ["Dan Cheail"]
|
10
|
+
spec.email = ["dan@undumb.com"]
|
11
|
+
spec.description = %q{A very simple API for logging and retreiving the progress of a given background task using Redis.}
|
12
|
+
spec.summary = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport", "~> 4.0.0"
|
22
|
+
spec.add_dependency "redis", "~> 3.0.0"
|
23
|
+
spec.add_dependency "redis-namespace", "~> 1.3.1"
|
24
|
+
|
25
|
+
spec.add_development_dependency "mock_redis"
|
26
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
Bundler.require(:default, :development)
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
require 'mock_redis'
|
5
|
+
|
6
|
+
require 'progress_tracker'
|
7
|
+
|
8
|
+
# FAKE REDIS!
|
9
|
+
ProgressTracker::Base.redis_connection = MockRedis.new
|
10
|
+
|
11
|
+
shared_examples "a ProgressTracker::Tracker instance" do
|
12
|
+
let(:setter_base) { ProgressTracker::Base.new(:paired_thing) }
|
13
|
+
let(:getter) { ProgressTracker::Base.new(:paired_thing) }
|
14
|
+
|
15
|
+
it "remembers the current progress" do
|
16
|
+
setter.progress 50
|
17
|
+
expect(_result(getter, :progress, setter.current_tracked_object)).to eql(50)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "ensures that progress is an integer" do
|
21
|
+
setter.progress 50.34
|
22
|
+
expect(_result(getter, :progress, setter.current_tracked_object)).to eql(50)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "remembers the latest message" do
|
26
|
+
msg = "So long, and thanks for all the fish."
|
27
|
+
|
28
|
+
setter.message msg
|
29
|
+
expect(_result(getter, :message, setter.current_tracked_object)).to eql(msg)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
it "remembers several things at once" do
|
34
|
+
things = { progress: 42, message: "Share and enjoy." }
|
35
|
+
setter.update things
|
36
|
+
|
37
|
+
expect(getter.to_hash[setter.current_tracked_object]).to eql(things)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "remembers arbitrary keys / values" do
|
41
|
+
setter.update foo: "bar!"
|
42
|
+
expect(getter.to_hash[setter.current_tracked_object][:foo]).to eql("bar!")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
describe ProgressTracker::Base do
|
48
|
+
|
49
|
+
# make sure we're clearing out fake-redis after each test
|
50
|
+
after(:each) do
|
51
|
+
ProgressTracker::Base.redis_connection.flushdb
|
52
|
+
end
|
53
|
+
|
54
|
+
# shortcut for accessing deep hash keys
|
55
|
+
def _result(pt, field, key = :_base)
|
56
|
+
pt.to_hash[key][field]
|
57
|
+
end
|
58
|
+
|
59
|
+
let(:pt) { ProgressTracker::Base.new(:derp) }
|
60
|
+
|
61
|
+
it "must be initialized with at least a simple key" do
|
62
|
+
expect { ProgressTracker::Base.new }.to raise_error
|
63
|
+
expect { ProgressTracker::Base.new(:derp) }.not_to raise_error
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
it "can be initialized using a class / id compound key" do
|
68
|
+
expect { ProgressTracker::Base.new(:thing, 100) }.not_to raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
it "returns sane defaults" do
|
73
|
+
expect(pt.to_hash).to eql({ _base: { progress: 0, message: "" } })
|
74
|
+
end
|
75
|
+
|
76
|
+
it "can track mutliple sub-objects" do
|
77
|
+
pt.track :foo
|
78
|
+
pt.track :bar, 100
|
79
|
+
|
80
|
+
expect(pt.to_hash).to have_key(:foo)
|
81
|
+
expect(pt.to_hash).to have_key(:bar_100)
|
82
|
+
end
|
83
|
+
|
84
|
+
# it "ensures that any tracked sub-objects are re-cached when initialising a new tracker" do
|
85
|
+
# pt.track :foo
|
86
|
+
# pt.track :bar, 100
|
87
|
+
|
88
|
+
# pt2 = ProgressTracker::Base.new(pt.base_key)
|
89
|
+
|
90
|
+
# expect(pt2.to_hash).to have_key(:foo)
|
91
|
+
# expect(pt2.to_hash).to have_key(:bar_100)
|
92
|
+
# end
|
93
|
+
|
94
|
+
context "when operating on the base object" do
|
95
|
+
it_behaves_like "a ProgressTracker::Tracker instance" do
|
96
|
+
let(:setter) { setter_base }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
context "when operating on a simple sub-object" do
|
102
|
+
it_behaves_like "a ProgressTracker::Tracker instance" do
|
103
|
+
before(:each) { setter_base.track :derp }
|
104
|
+
let(:setter) { setter_base.derp }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when tracking a compound-key sub-object" do
|
109
|
+
it_behaves_like "a ProgressTracker::Tracker instance" do
|
110
|
+
before(:each) { setter_base.track :derp, 100 }
|
111
|
+
let(:setter) { setter_base.derp(100) }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "can go to json, too!"
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: progress_tracker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Cheail
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: redis-namespace
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.3.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.3.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mock_redis
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.14'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.14'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: A very simple API for logging and retreiving the progress of a given
|
112
|
+
background task using Redis.
|
113
|
+
email:
|
114
|
+
- dan@undumb.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- .gitignore
|
120
|
+
- .rspec
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- lib/progress_tracker.rb
|
126
|
+
- lib/progress_tracker/base.rb
|
127
|
+
- lib/progress_tracker/version.rb
|
128
|
+
- progress_tracker.gemspec
|
129
|
+
- spec/progress_tracker_spec.rb
|
130
|
+
homepage: ''
|
131
|
+
licenses:
|
132
|
+
- MIT
|
133
|
+
metadata: {}
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - '>='
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubyforge_project:
|
150
|
+
rubygems_version: 2.1.4
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: ''
|
154
|
+
test_files:
|
155
|
+
- spec/progress_tracker_spec.rb
|