honkster-bin 0.6.3

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 John Nunemaker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,20 @@
1
+ = Bin
2
+
3
+ ActiveSupport MongoDB Cache store.
4
+
5
+ == Supports
6
+
7
+ * Ruby 1.8.7 and Ruby 1.9.1.
8
+ * ActiveSupport 2 and 3
9
+
10
+ == Note on Patches/Pull Requests
11
+
12
+ * Fork the project.
13
+ * Make your feature addition or bug fix.
14
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
15
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
16
+ * Send me a pull request. Bonus points for topic branches.
17
+
18
+ == Copyright
19
+
20
+ Copyright (c) 2010 John Nunemaker. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'spec/rake/spectask'
4
+ require File.expand_path('../lib/bin/version', __FILE__)
5
+
6
+ namespace :spec do
7
+ Spec::Rake::SpecTask.new(:all) do |t|
8
+ t.ruby_opts << '-rubygems'
9
+ t.verbose = true
10
+ end
11
+
12
+ task :as2 do
13
+ sh 'ACTIVE_SUPPORT_VERSION="<= 2.3.8" rake spec:all'
14
+ end
15
+
16
+ task :as3 do
17
+ sh 'ACTIVE_SUPPORT_VERSION=">= 3.0.0.beta3" rake spec:all'
18
+ end
19
+ end
20
+
21
+ desc 'Runs all specs against Active Support 2 and 3'
22
+ task :spec do
23
+ Rake::Task['spec:as2'].invoke
24
+ Rake::Task['spec:as3'].invoke
25
+ end
26
+
27
+ task :default => :spec
28
+
29
+ desc 'Builds the gem'
30
+ task :build do
31
+ sh "gem build bin.gemspec"
32
+ end
33
+
34
+ desc 'Builds and installs the gem'
35
+ task :install => :build do
36
+ sh "gem install bin-#{Bin::Version}"
37
+ end
38
+
39
+ desc 'Tags version, pushes to remote, and pushes gem'
40
+ task :release => :build do
41
+ sh "git tag v#{Bin::Version}"
42
+ sh "git push origin master"
43
+ sh "git push origin v#{Bin::Version}"
44
+ sh "gem push bin-#{Bin::Version}.gem"
45
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: UTF-8
2
+ module Bin
3
+ class Compatibility < ActiveSupport::Cache::Store
4
+ def increment(key, amount=1)
5
+ yield
6
+ end
7
+
8
+ def decrement(key, amount=1)
9
+ yield
10
+ end
11
+ end
12
+
13
+ if ActiveSupport::VERSION::STRING < '3'
14
+ class Compatibility
15
+ def write(key, value, options=nil, &block)
16
+ super(key, value, options)
17
+ yield
18
+ end
19
+
20
+ def read(key, options=nil, &block)
21
+ super
22
+ yield
23
+ end
24
+
25
+ def delete(key, options=nil, &block)
26
+ super
27
+ yield
28
+ end
29
+
30
+ def delete_matched(matcher, options=nil, &block)
31
+ super
32
+ yield
33
+ end
34
+
35
+ def exist?(key, options=nil, &block)
36
+ super
37
+ yield
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/bin/store.rb ADDED
@@ -0,0 +1,84 @@
1
+ # encoding: UTF-8
2
+ module Bin
3
+ class Store < Compatibility
4
+ attr_reader :collection, :options
5
+
6
+ def initialize(collection, options={})
7
+ @collection, @options = collection, options
8
+ end
9
+
10
+ def expires_in
11
+ @expires_in ||= options[:expires_in] || 1.year
12
+ end
13
+
14
+ def write(key, value, options={})
15
+ key = key.to_s
16
+ super do
17
+ expires = Time.now.utc + ((options && options[:expires_in]) || expires_in)
18
+ raw = !!options[:raw]
19
+ value = raw ? value : BSON::Binary.new(Marshal.dump(value))
20
+ doc = {:_id => key, :value => value, :expires_at => expires, :raw => raw}
21
+ collection.save(doc)
22
+ end
23
+ end
24
+
25
+ def read(key, options=nil)
26
+ super do
27
+ if doc = collection.find_one(:_id => key.to_s, :expires_at => {'$gt' => Time.now.utc})
28
+ doc['raw'] ? doc['value'] : Marshal.load(doc['value'].to_s)
29
+ end
30
+ end
31
+ end
32
+
33
+ def delete(key, options=nil)
34
+ super do
35
+ collection.remove(:_id => key.to_s)
36
+ end
37
+ end
38
+
39
+ def delete_matched(matcher, options=nil)
40
+ super do
41
+ collection.remove(:_id => matcher)
42
+ end
43
+ end
44
+
45
+ def exist?(key, options=nil)
46
+ super do
47
+ !read(key, options).nil?
48
+ end
49
+ end
50
+
51
+ def increment(key, amount=1)
52
+ super do
53
+ counter_key_upsert(key, amount)
54
+ end
55
+ end
56
+
57
+ def decrement(key, amount=1)
58
+ super do
59
+ counter_key_upsert(key, -amount.abs)
60
+ end
61
+ end
62
+
63
+ def clear
64
+ collection.remove
65
+ end
66
+
67
+ def stats
68
+ collection.stats
69
+ end
70
+
71
+ private
72
+ def counter_key_upsert(key, amount)
73
+ key = key.to_s
74
+ collection.update(
75
+ {:_id => key}, {
76
+ '$inc' => {:value => amount},
77
+ '$set' => {
78
+ :expires_at => Time.now.utc + 1.year,
79
+ :raw => true
80
+ },
81
+ }, :upsert => true)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: UTF-8
2
+ module Bin
3
+ Version = '0.6.3'
4
+ end
data/lib/bin.rb ADDED
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+ require 'active_support/all'
3
+ require 'active_support/version'
4
+ require 'mongo'
5
+
6
+ module Bin
7
+ autoload :Compatibility, 'bin/compatibility'
8
+ autoload :Store, 'bin/store'
9
+ autoload :Version, 'bin/version'
10
+ end
@@ -0,0 +1,210 @@
1
+ require 'helper'
2
+
3
+ describe Bin::Store do
4
+ before(:each) do
5
+ DB.collections.each do |collection|
6
+ collection.remove
7
+ collection.drop_indexes
8
+ end
9
+ end
10
+
11
+ let(:collection) { DB['bin_cache'] }
12
+ let(:store) { Bin::Store.new(collection) }
13
+
14
+ it "has a collection" do
15
+ store.collection.should == collection
16
+ end
17
+
18
+ it "defaults expires_in to 1.year" do
19
+ store.expires_in.should == 1.year
20
+ end
21
+
22
+ it "can set default expires_in" do
23
+ Bin::Store.new(collection, :expires_in => 5.minutes).expires_in.should == 5.minutes
24
+ end
25
+
26
+ describe "#write" do
27
+ before(:each) do
28
+ store.write('foo', 'bar')
29
+ end
30
+ let(:document) { collection.find_one(:_id => 'foo') }
31
+
32
+ it "sets _id to key" do
33
+ document['_id'].should == 'foo'
34
+ end
35
+
36
+ it "sets value key to value" do
37
+ store.read('foo').should == 'bar'
38
+ end
39
+
40
+ it "should marshal value by default" do
41
+ document['value'].to_s.should == BSON::Binary.new(Marshal.dump('bar')).to_s
42
+ document['raw'].should be_false
43
+ end
44
+
45
+ it "should be able to store in raw format" do
46
+ store.write('foo', 'bar', :raw => true)
47
+ document['value'].should == 'bar'
48
+ document['raw'].should be_true
49
+ end
50
+
51
+ it "sets expires in to default if not provided" do
52
+ document['expires_at'].to_i.should == (Time.now.utc + 1.year).to_i
53
+ end
54
+
55
+ it "sets expires_at if expires_in provided" do
56
+ store.write('foo', 'bar', :expires_in => 5.seconds)
57
+ document['expires_at'].to_i.should == (Time.now.utc + 5.seconds).to_i
58
+ end
59
+
60
+ it "always sets key as string" do
61
+ store.write(:baz, 'wick')
62
+ doc = collection.find_one(:_id => 'baz')
63
+ doc.should_not be_nil
64
+ doc['_id'].should be_instance_of(String)
65
+ end
66
+ end
67
+
68
+ describe "#read" do
69
+ before(:each) do
70
+ store.write('foo', 'bar')
71
+ end
72
+ let(:document) { collection.find_one(:_id => 'foo') }
73
+
74
+ it "returns nil for key not found" do
75
+ store.read('non:existent:key').should be_nil
76
+ end
77
+
78
+ it "returns unmarshalled value key value for key found" do
79
+ store.read('foo').should == 'bar'
80
+ end
81
+
82
+ it "returns raw value if document raw key is true" do
83
+ store.write('foo', 'bar', :raw => true)
84
+ store.read('foo').should == 'bar'
85
+ end
86
+
87
+ it "returns nil for existing but expired key" do
88
+ collection.save(:_id => 'foo', :value => 'bar', :expires_at => 5.seconds.ago)
89
+ store.read('foo').should be_nil
90
+ end
91
+
92
+ it "return value for existing and not expired key" do
93
+ store.write('foo', 'bar', :expires_in => 20.seconds)
94
+ store.read('foo').should == 'bar'
95
+ end
96
+
97
+ it "works with symbol" do
98
+ store.read(:foo).should == 'bar'
99
+ end
100
+ end
101
+
102
+ describe "#delete" do
103
+ before(:each) do
104
+ store.write('foo', 'bar')
105
+ end
106
+
107
+ it "delete key from cache" do
108
+ store.read('foo').should_not be_nil
109
+ store.delete('foo')
110
+ store.read('foo').should be_nil
111
+ end
112
+
113
+ it "works with symbol" do
114
+ store.read(:foo).should_not be_nil
115
+ store.delete(:foo)
116
+ store.read(:foo).should be_nil
117
+ end
118
+ end
119
+
120
+ describe "#delete_matched" do
121
+ before(:each) do
122
+ store.write('foo1', 'bar')
123
+ store.write('foo2', 'bar')
124
+ store.write('baz', 'wick')
125
+ end
126
+
127
+ it "deletes matching keys" do
128
+ store.read('foo1').should_not be_nil
129
+ store.read('foo2').should_not be_nil
130
+ store.delete_matched(/foo/)
131
+ store.read('foo1').should be_nil
132
+ store.read('foo2').should be_nil
133
+ end
134
+
135
+ it "does not delete unmatching keys" do
136
+ store.delete_matched('foo')
137
+ store.read('baz').should_not be_nil
138
+ end
139
+ end
140
+
141
+ describe "#exist?" do
142
+ before(:each) do
143
+ store.write('foo', 'bar')
144
+ end
145
+
146
+ it "returns true if key found" do
147
+ store.exist?('foo').should be_true
148
+ end
149
+
150
+ it "returns false if key not found" do
151
+ store.exist?('not:found:key').should be_false
152
+ end
153
+
154
+ it "works with symbol" do
155
+ store.exist?(:foo).should be_true
156
+ store.exist?(:notfoundkey).should be_false
157
+ end
158
+ end
159
+
160
+ describe "#clear" do
161
+ before(:each) do
162
+ store.write('foo', 'bar')
163
+ store.write('baz', 'wick')
164
+ end
165
+
166
+ it "clear all keys" do
167
+ collection.count.should == 2
168
+ store.clear
169
+ collection.count.should == 0
170
+ end
171
+ end
172
+
173
+ describe "#increment" do
174
+ it "increment key by amount" do
175
+ store.increment('views', 1)
176
+ store.read('views').should == 1
177
+ store.increment('views', 2)
178
+ store.read('views').should == 3
179
+ end
180
+
181
+ it "works with symbol" do
182
+ store.increment(:views, 2)
183
+ store.read(:views).should == 2
184
+ end
185
+ end
186
+
187
+ describe "#decrement" do
188
+ it "decrement key by amount" do
189
+ store.increment('views', 5)
190
+ store.decrement('views', 2)
191
+ store.read('views').should == 3
192
+ store.decrement('views', 2)
193
+ store.read('views').should == 1
194
+ end
195
+
196
+ it "works with symbol" do
197
+ store.increment(:views, 2)
198
+ store.decrement(:views, 1)
199
+ store.read(:views).should == 1
200
+ end
201
+ end
202
+
203
+ describe "#stats" do
204
+ it "returns stats" do
205
+ %w[ns count size].each do |key|
206
+ store.stats.should have_key(key)
207
+ end
208
+ end
209
+ end
210
+ end
data/spec/bin_spec.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'helper'
2
+
3
+ describe Bin do
4
+ it "autoloads Store" do
5
+ lambda { Bin::Store }.should_not raise_error(NameError)
6
+ end
7
+
8
+ it "autoloads Compatibility" do
9
+ lambda { Bin::Compatibility }.should_not raise_error(NameError)
10
+ end
11
+
12
+ it "autoloads Version" do
13
+ lambda { Bin::Version }.should_not raise_error(NameError)
14
+ end
15
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,11 @@
1
+ gem 'activesupport', ENV['ACTIVE_SUPPORT_VERSION']
2
+
3
+ $:.unshift(File.expand_path('../../lib', __FILE__))
4
+
5
+ require 'bin'
6
+ require 'spec'
7
+
8
+ connection = Mongo::Connection.new
9
+ DB = connection.db('bin-store-test')
10
+
11
+ puts "\n--- Active Support Version: #{ActiveSupport::VERSION::STRING} ---\n"
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --timeout
3
+ 20
4
+ --diff
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: honkster-bin
3
+ version: !ruby/object:Gem::Version
4
+ hash: 1
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 3
10
+ version: 0.6.3
11
+ platform: ruby
12
+ authors:
13
+ - John Nunemaker
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-19 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mongo
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 17
30
+ segments:
31
+ - 1
32
+ - 1
33
+ - 1
34
+ version: 1.1.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: activesupport
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 5
46
+ segments:
47
+ - 2
48
+ - 3
49
+ version: "2.3"
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: rspec
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 27
61
+ segments:
62
+ - 1
63
+ - 3
64
+ - 0
65
+ version: 1.3.0
66
+ type: :development
67
+ version_requirements: *id003
68
+ description:
69
+ email:
70
+ - nunemaker@gmail.com
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - lib/bin/compatibility.rb
79
+ - lib/bin/version.rb
80
+ - lib/bin/store.rb
81
+ - lib/bin.rb
82
+ - spec/helper.rb
83
+ - spec/bin_spec.rb
84
+ - spec/spec.opts
85
+ - spec/bin/store_spec.rb
86
+ - LICENSE
87
+ - Rakefile
88
+ - README.rdoc
89
+ has_rdoc: true
90
+ homepage: http://github.com/jnunemaker/bin
91
+ licenses: []
92
+
93
+ post_install_message:
94
+ rdoc_options: []
95
+
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
106
+ version: "0"
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: 3
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ requirements: []
117
+
118
+ rubyforge_project:
119
+ rubygems_version: 1.3.7
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: ActiveSupport MongoDB Cache store.
123
+ test_files: []
124
+