boffin 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -0
- data/Gemfile +1 -1
- data/README.md +1 -0
- data/Rakefile +1 -1
- data/boffin.gemspec +3 -2
- data/lib/boffin.rb +3 -4
- data/lib/boffin/tracker.rb +6 -4
- data/lib/boffin/utils.rb +19 -7
- data/lib/boffin/version.rb +1 -1
- data/spec/boffin/config_spec.rb +2 -2
- data/spec/boffin/hit_spec.rb +4 -4
- data/spec/boffin/keyspace_spec.rb +7 -1
- data/spec/boffin/trackable_spec.rb +1 -1
- data/spec/boffin/tracker_spec.rb +12 -12
- data/spec/boffin/utils_spec.rb +14 -14
- data/spec/boffin_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- metadata +21 -10
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -15,6 +15,7 @@ weighted combinations of different types of hits.
|
|
15
15
|
Resources
|
16
16
|
---------
|
17
17
|
|
18
|
+
* [Documentation](http://rubydoc.info/github/heycarsten/boffin/master/frames)
|
18
19
|
* [Source Code](https://github.com/heycarsten/boffin)
|
19
20
|
* [Issue Tracker](https://github.com/heycarsten/boffin/issues)
|
20
21
|
* [Test Suite](https://github.com/heycarsten/boffin/tree/master/spec)
|
data/Rakefile
CHANGED
data/boffin.gemspec
CHANGED
@@ -11,13 +11,14 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.summary = 'Hit tracking library for Ruby using Redis'
|
12
12
|
s.has_rdoc = 'yard'
|
13
13
|
s.rubyforge_project = 'boffin'
|
14
|
-
s.files = `git ls-files`.split(
|
15
|
-
s.test_files = `git ls-files -- spec/*`.split(
|
14
|
+
s.files = `git ls-files`.split(/\n/)
|
15
|
+
s.test_files = `git ls-files -- spec/*`.split(/\n/)
|
16
16
|
s.require_paths = ['lib']
|
17
17
|
|
18
18
|
s.add_dependency 'redis', '>= 2.2'
|
19
19
|
s.add_development_dependency 'rspec', '~> 2.6'
|
20
20
|
s.add_development_dependency 'timecop'
|
21
|
+
s.add_development_dependency 'bundler', '>= 1.0.14'
|
21
22
|
|
22
23
|
s.description = <<-END
|
23
24
|
Boffin is a library for tracking hits to things in your Ruby application. Things
|
data/lib/boffin.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'base64'
|
2
1
|
require 'date'
|
3
2
|
require 'time'
|
4
3
|
require 'redis'
|
@@ -24,9 +23,9 @@ module Boffin
|
|
24
23
|
|
25
24
|
# The way Time should be formatted for each interval type
|
26
25
|
INTERVAL_FORMATS = {
|
27
|
-
hours
|
28
|
-
days
|
29
|
-
months
|
26
|
+
:hours => '%F-%H',
|
27
|
+
:days => '%F',
|
28
|
+
:months => '%Y-%m' }
|
30
29
|
|
31
30
|
# Different interval types
|
32
31
|
INTERVAL_TYPES = INTERVAL_FORMATS.keys
|
data/lib/boffin/tracker.rb
CHANGED
@@ -91,6 +91,8 @@ module Boffin
|
|
91
91
|
# Perform union for hit counts over the last _n_ months.
|
92
92
|
# @example Return IDs of most viewed and liked listings in the past 6 days with scores
|
93
93
|
# @tracker.top({ views: 1, likes: 1 }, counts: true, days: 6)
|
94
|
+
# @example Return IDS of most viewed and liked listings in the past 6 days with scores (Alternate syntax)
|
95
|
+
# @tracker.top([[:views, 1], [:likes, 1]], counts: true, days: 6)
|
94
96
|
# @example Return IDs of most viewed listings in the past 12 hours
|
95
97
|
# @tracker.top(:views, hours: 12)
|
96
98
|
# @note
|
@@ -178,7 +180,7 @@ module Boffin
|
|
178
180
|
weights.keys.each { |t| union(ks, t, unit, size, opts) }
|
179
181
|
keys = weights.keys.map { |t| ks.hits_union(t, unit, size) }
|
180
182
|
zfetch(ks.hits_union_multi(weights, unit, size), keys, {
|
181
|
-
weights
|
183
|
+
:weights => weights.values
|
182
184
|
}.merge(opts))
|
183
185
|
end
|
184
186
|
|
@@ -194,8 +196,8 @@ module Boffin
|
|
194
196
|
# @see #zrange
|
195
197
|
def zfetch(storkey, keys, opts = {})
|
196
198
|
zrangeopts = {
|
197
|
-
counts
|
198
|
-
order
|
199
|
+
:counts => opts.delete(:counts),
|
200
|
+
:order => (opts.delete(:order) || :desc).to_sym }
|
199
201
|
if redis.zcard(storkey) == 0
|
200
202
|
redis.zunionstore(storkey, keys, opts)
|
201
203
|
redis.expire(storkey, @config.cache_expire_secs)
|
@@ -213,7 +215,7 @@ module Boffin
|
|
213
215
|
# option is `true` it returns an array of pairs where the first value is
|
214
216
|
# the member, and the second value is the member's score.
|
215
217
|
def zrange(key, opts)
|
216
|
-
args = [key, 0, -1, opts[:counts] ? { withscores
|
218
|
+
args = [key, 0, -1, opts[:counts] ? { :withscores => true } : {}]
|
217
219
|
result = case opts[:order]
|
218
220
|
when :asc then redis.zrange(*args)
|
219
221
|
when :desc then redis.zrevrange(*args)
|
data/lib/boffin/utils.rb
CHANGED
@@ -13,9 +13,9 @@ module Boffin
|
|
13
13
|
|
14
14
|
# Number of seconds for a single value of each unit
|
15
15
|
SECONDS_IN_UNIT = {
|
16
|
-
hours
|
17
|
-
days
|
18
|
-
months
|
16
|
+
:hours => SECONDS_IN_HOUR,
|
17
|
+
:days => SECONDS_IN_DAY,
|
18
|
+
:months => SECONDS_IN_MONTH
|
19
19
|
}
|
20
20
|
|
21
21
|
module_function
|
@@ -45,6 +45,18 @@ module Boffin
|
|
45
45
|
obj.respond_to?(:empty?) ? obj.empty? : !obj
|
46
46
|
end
|
47
47
|
|
48
|
+
# @param [Object] obj any Ruby object
|
49
|
+
# @return [true, false]
|
50
|
+
# `true` if the provided object responds to :id, other than it's
|
51
|
+
# internal object identifier
|
52
|
+
# `false` if the object does not respond to :id
|
53
|
+
def respond_to_id?(obj)
|
54
|
+
# NOTE: this feels like a hack. I'm sure there is a more elegant way
|
55
|
+
# to determine whether the :id method is the built in Object#id but
|
56
|
+
# I can't think of it
|
57
|
+
obj.respond_to?(:id) and obj.id != obj.object_id
|
58
|
+
end
|
59
|
+
|
48
60
|
# Pulls time interval information from a hash of options.
|
49
61
|
# @example
|
50
62
|
# extract_time_unit(this: 'is ignored', days: 6, so_is: 'this')
|
@@ -134,13 +146,13 @@ module Boffin
|
|
134
146
|
# generated value will be Base64 encoded.
|
135
147
|
# @return [String]
|
136
148
|
def object_as_identifier(obj, opts = {})
|
137
|
-
if obj.respond_to?(:as_member) ||
|
149
|
+
if obj.respond_to?(:as_member) || respond_to_id?(obj)
|
138
150
|
''.tap do |s|
|
139
151
|
s << "#{underscore(obj.class)}:" if opts[:namespace]
|
140
152
|
s << (obj.respond_to?(:as_member) ? obj.as_member : obj.id).to_s
|
141
153
|
end
|
142
154
|
else
|
143
|
-
opts[:encode] ?
|
155
|
+
opts[:encode] ? [obj.to_s].pack("m0").chomp : obj.to_s
|
144
156
|
end
|
145
157
|
end
|
146
158
|
|
@@ -157,14 +169,14 @@ module Boffin
|
|
157
169
|
# @return [String] A string that can be used as a member in {Keyspace#hits}.
|
158
170
|
# @see #object_as_identifier
|
159
171
|
def object_as_session_identifier(obj)
|
160
|
-
object_as_identifier(obj, namespace
|
172
|
+
object_as_identifier(obj, :namespace => true)
|
161
173
|
end
|
162
174
|
|
163
175
|
# @param [#as_member, #id, #to_s] obj
|
164
176
|
# @return [String] A string that can be used as part of a Redis key
|
165
177
|
# @see #object_as_identifier
|
166
178
|
def object_as_key(obj)
|
167
|
-
object_as_identifier(obj, encode
|
179
|
+
object_as_identifier(obj, :encode => true)
|
168
180
|
end
|
169
181
|
|
170
182
|
end
|
data/lib/boffin/version.rb
CHANGED
data/spec/boffin/config_spec.rb
CHANGED
@@ -28,14 +28,14 @@ describe Boffin::Config do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'can be sent a hash' do
|
31
|
-
conf = Boffin::Config.new(namespace
|
31
|
+
conf = Boffin::Config.new(:namespace => 'hello')
|
32
32
|
conf.namespace.should == 'hello'
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
describe '#merge' do
|
37
37
|
it 'copies the existing instance' do
|
38
|
-
newconf = subject.merge(namespace
|
38
|
+
newconf = subject.merge(:namespace => 'carsten')
|
39
39
|
newconf.namespace.should == 'carsten'
|
40
40
|
subject.namespace.should == 'boffin'
|
41
41
|
end
|
data/spec/boffin/hit_spec.rb
CHANGED
@@ -16,9 +16,9 @@ describe Boffin::Hit, '::new' do
|
|
16
16
|
it 'stores hit data under the appropriate keys' do
|
17
17
|
Boffin::Hit.new(@tracker, :tests, @ditty, [nil, @user])
|
18
18
|
[:hours, :days, :months].each do |interval|
|
19
|
-
@tracker.top(:tests, interval => 1, counts
|
19
|
+
@tracker.top(:tests, interval => 1, :counts => true).
|
20
20
|
should == [['1', 1]]
|
21
|
-
@tracker.top(:tests, interval => 1, counts
|
21
|
+
@tracker.top(:tests, interval => 1, :counts => true, :unique => true).
|
22
22
|
should == [['1', 1]]
|
23
23
|
end
|
24
24
|
@tracker.hit_count(:tests, @ditty).should == 1
|
@@ -29,9 +29,9 @@ describe Boffin::Hit, '::new' do
|
|
29
29
|
Boffin::Hit.new(@tracker, :tests, @ditty, [nil, @user])
|
30
30
|
Boffin::Hit.new(@tracker, :tests, @ditty, [nil, @user])
|
31
31
|
[:hours, :days, :months].each do |interval|
|
32
|
-
@tracker.top(:tests, interval => 1, counts
|
32
|
+
@tracker.top(:tests, interval => 1, :counts => true).
|
33
33
|
should == [['1', 2]]
|
34
|
-
@tracker.top(:tests, interval => 1, counts
|
34
|
+
@tracker.top(:tests, interval => 1, :counts => true, :unique => true).
|
35
35
|
should == [['1', 1]]
|
36
36
|
end
|
37
37
|
@tracker.hit_count_for_session_id(:tests, @ditty, @user).should == 2
|
@@ -42,7 +42,13 @@ describe Boffin::Keyspace do
|
|
42
42
|
|
43
43
|
describe '#hits_union_multi' do
|
44
44
|
specify do
|
45
|
-
|
45
|
+
weighted_hit_types =
|
46
|
+
if RUBY_VERSION < '1.9'
|
47
|
+
[[:views, 1], [:likes, 3]]
|
48
|
+
else
|
49
|
+
{ :views => 1, :likes => 3 }
|
50
|
+
end
|
51
|
+
@ks.hits_union_multi(weighted_hit_types, :days, 5).
|
46
52
|
should == 'b:mock_ditty:views_1_likes_3:hits:current.days_5'
|
47
53
|
end
|
48
54
|
end
|
@@ -21,7 +21,7 @@ describe Boffin::Trackable do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'delegates ::top_ids to the Tracker instance' do
|
24
|
-
MockTrackableInjected.top_ids(:views, days
|
24
|
+
MockTrackableInjected.top_ids(:views, :days => 1).should == ['1']
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'delegates #hit_count to the Tracker instance' do
|
data/spec/boffin/tracker_spec.rb
CHANGED
@@ -55,14 +55,14 @@ describe Boffin::Tracker do
|
|
55
55
|
|
56
56
|
describe '#hit' do
|
57
57
|
it 'throws an error if the hit type is not in the list' do
|
58
|
-
|
58
|
+
lambda { @tracker.hit(:view, @instance1) }.
|
59
59
|
should raise_error Boffin::UndefinedHitTypeError
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
63
|
describe '#hit_count' do
|
64
64
|
it 'throws an error if the hit type is not in the list' do
|
65
|
-
|
65
|
+
lambda { @tracker.hit_count(:view, @instance1) }.
|
66
66
|
should raise_error Boffin::UndefinedHitTypeError
|
67
67
|
end
|
68
68
|
|
@@ -77,7 +77,7 @@ describe Boffin::Tracker do
|
|
77
77
|
|
78
78
|
describe '#uhit_count' do
|
79
79
|
it 'throws an error if the hit type is not in the list' do
|
80
|
-
|
80
|
+
lambda { @tracker.uhit_count(:view, @instance1) }.
|
81
81
|
should raise_error Boffin::UndefinedHitTypeError
|
82
82
|
end
|
83
83
|
|
@@ -92,7 +92,7 @@ describe Boffin::Tracker do
|
|
92
92
|
|
93
93
|
describe '#hit_count_for_session_id' do
|
94
94
|
it 'throws an error if the hit type is not in the list' do
|
95
|
-
|
95
|
+
lambda { @tracker.hit_count_for_session_id(:view, @instance1, 'sess.1') }.
|
96
96
|
should raise_error Boffin::UndefinedHitTypeError
|
97
97
|
end
|
98
98
|
|
@@ -107,32 +107,32 @@ describe Boffin::Tracker do
|
|
107
107
|
|
108
108
|
describe '#top' do
|
109
109
|
it 'throws an error if passed hit type is invalid' do
|
110
|
-
|
110
|
+
lambda { @tracker.top(:view, :days => 3) }.
|
111
111
|
should raise_error Boffin::UndefinedHitTypeError
|
112
112
|
end
|
113
113
|
|
114
114
|
it 'throws an error if passed weights with hit type that is invalid' do
|
115
|
-
|
115
|
+
lambda { @tracker.top({ :view => 1 }, :days => 3) }.
|
116
116
|
should raise_error Boffin::UndefinedHitTypeError
|
117
117
|
end
|
118
118
|
|
119
119
|
it 'returns ids ordered by hit counts of weighted totals' do
|
120
|
-
ids = @tracker.top({ views
|
120
|
+
ids = @tracker.top({ :views => 1, :likes => 2 }, :days => 3)
|
121
121
|
ids.should == ['300', '200', '100']
|
122
122
|
end
|
123
123
|
|
124
124
|
it 'returns ids ordered by total counts of a specific hit type' do
|
125
|
-
ids = @tracker.top(:views, days
|
125
|
+
ids = @tracker.top(:views, :days => 3)
|
126
126
|
ids.should == ['300', '100', '200']
|
127
127
|
end
|
128
128
|
|
129
129
|
it 'returns ids in ascending order when passed { order: "asc" } as an option' do
|
130
|
-
ids = @tracker.top(:views, days
|
130
|
+
ids = @tracker.top(:views, :days => 3, :order => 'asc')
|
131
131
|
ids.should == ['200', '100', '300']
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'returns ids and counts when passed { counts: true } as an option' do
|
135
|
-
ids = @tracker.top(:views, days
|
135
|
+
ids = @tracker.top(:views, :days => 3, :counts => true)
|
136
136
|
ids.should == [
|
137
137
|
['300', 12],
|
138
138
|
['100', 8],
|
@@ -141,7 +141,7 @@ describe Boffin::Tracker do
|
|
141
141
|
end
|
142
142
|
|
143
143
|
it 'returns ids based on unique hit data when passed { unique: true } as an option' do
|
144
|
-
ids = @tracker.top(:views, days
|
144
|
+
ids = @tracker.top(:views, :days => 3, :counts => true, :unique => true)
|
145
145
|
ids.should == [
|
146
146
|
['300', 7],
|
147
147
|
['200', 5],
|
@@ -159,4 +159,4 @@ describe Boffin::Tracker do
|
|
159
159
|
@tracker.keyspace(true).unique_namespace?.should be_true
|
160
160
|
end
|
161
161
|
end
|
162
|
-
end
|
162
|
+
end
|
data/spec/boffin/utils_spec.rb
CHANGED
@@ -44,12 +44,12 @@ describe Boffin::Utils do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
describe '::extract_time_unit' do
|
47
|
-
specify { subject.extract_time_unit(hours
|
48
|
-
specify { subject.extract_time_unit(days
|
49
|
-
specify { subject.extract_time_unit(months
|
47
|
+
specify { subject.extract_time_unit(:hours => 6).should == [:hours, 6] }
|
48
|
+
specify { subject.extract_time_unit(:days => 2).should == [:days, 2] }
|
49
|
+
specify { subject.extract_time_unit(:months => 3).should == [:months, 3] }
|
50
50
|
|
51
51
|
it 'throws an error if no time unit pair exists in the hash' do
|
52
|
-
lambda { subject.extract_time_unit(fun
|
52
|
+
lambda { subject.extract_time_unit(:fun => 'times') }.
|
53
53
|
should raise_error ArgumentError
|
54
54
|
end
|
55
55
|
end
|
@@ -57,12 +57,12 @@ describe Boffin::Utils do
|
|
57
57
|
describe '::time_ago' do
|
58
58
|
before { @time = Time.local(2011, 2, 15, 12) }
|
59
59
|
|
60
|
-
specify { subject.time_ago(@time, hours
|
61
|
-
specify { subject.time_ago(@time, days
|
62
|
-
specify { subject.time_ago(@time, months
|
60
|
+
specify { subject.time_ago(@time, :hours => 6).should == Time.local(2011, 2, 15, 6) }
|
61
|
+
specify { subject.time_ago(@time, :days => 5).should == Time.local(2011, 2, 10, 12) }
|
62
|
+
specify { subject.time_ago(@time, :months => 1).should == Time.local(2011, 1, 16, 12) } # A "month" is 30 days
|
63
63
|
|
64
64
|
it 'throws an error if no time unit pair exists in the hash' do
|
65
|
-
lambda { subject.time_ago(@time, fun
|
65
|
+
lambda { subject.time_ago(@time, :fun => 'fail') }.
|
66
66
|
should raise_error ArgumentError
|
67
67
|
end
|
68
68
|
end
|
@@ -70,16 +70,16 @@ describe Boffin::Utils do
|
|
70
70
|
describe '::time_ago_range' do
|
71
71
|
before { @time = Time.local(2011, 2, 15, 12) }
|
72
72
|
|
73
|
-
specify { subject.time_ago_range(@time, hours
|
74
|
-
specify { subject.time_ago_range(@time, months
|
73
|
+
specify { subject.time_ago_range(@time, :hours => 6).size.should == 6 }
|
74
|
+
specify { subject.time_ago_range(@time, :months => 1).size.should == 1 }
|
75
75
|
|
76
76
|
specify do
|
77
|
-
subject.time_ago_range(@time, days
|
77
|
+
subject.time_ago_range(@time, :days => 2).
|
78
78
|
should == [Time.local(2011, 2, 14, 12), Time.local(2011, 2, 15, 12)]
|
79
79
|
end
|
80
80
|
|
81
81
|
specify do
|
82
|
-
subject.time_ago_range(@time, days
|
82
|
+
subject.time_ago_range(@time, :days => 3).
|
83
83
|
should == [
|
84
84
|
Time.local(2011, 2, 13, 12),
|
85
85
|
Time.local(2011, 2, 14, 12),
|
@@ -88,13 +88,13 @@ describe Boffin::Utils do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
it 'ranges from n days away upto @time' do
|
91
|
-
times = subject.time_ago_range(@time, days
|
91
|
+
times = subject.time_ago_range(@time, :days => 4)
|
92
92
|
times.first.should == Time.local(2011, 2, 12, 12)
|
93
93
|
times.last.should == @time
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'throws an error if no time unit pair exists in the hash' do
|
97
|
-
lambda { subject.time_ago_range(@time, fun
|
97
|
+
lambda { subject.time_ago_range(@time, :fun => 'crash') }.
|
98
98
|
should raise_error ArgumentError
|
99
99
|
end
|
100
100
|
end
|
data/spec/boffin_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boffin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-08
|
12
|
+
date: 2011-09-08 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &70347564151120 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '2.2'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70347564151120
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70347564150300 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '2.6'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70347564150300
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: timecop
|
38
|
-
requirement: &
|
38
|
+
requirement: &70347564149720 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,18 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70347564149720
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: &70347564149100 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.14
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70347564149100
|
47
58
|
description: ! 'Boffin is a library for tracking hits to things in your Ruby application.
|
48
59
|
Things
|
49
60
|
|
@@ -100,7 +111,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
111
|
version: '0'
|
101
112
|
segments:
|
102
113
|
- 0
|
103
|
-
hash:
|
114
|
+
hash: 3845958252376638612
|
104
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
@@ -109,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
120
|
version: '0'
|
110
121
|
segments:
|
111
122
|
- 0
|
112
|
-
hash:
|
123
|
+
hash: 3845958252376638612
|
113
124
|
requirements: []
|
114
125
|
rubyforge_project: boffin
|
115
126
|
rubygems_version: 1.8.6
|