bin 0.5

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,77 @@
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=nil)
15
+ super do
16
+ expires = Time.now.utc + ((options && options[:expires_in]) || expires_in)
17
+ doc = {:_id => key, :value => value, :expires_at => expires}
18
+ collection.save(doc)
19
+ end
20
+ end
21
+
22
+ def read(key, options=nil)
23
+ super do
24
+ if doc = collection.find_one(:_id => key, :expires_at => {'$gt' => Time.now.utc})
25
+ doc['value']
26
+ end
27
+ end
28
+ end
29
+
30
+ def delete(key, options=nil)
31
+ super do
32
+ collection.remove(:_id => key)
33
+ end
34
+ end
35
+
36
+ def delete_matched(matcher, options=nil)
37
+ super do
38
+ collection.remove(:_id => matcher)
39
+ end
40
+ end
41
+
42
+ def exist?(key, options=nil)
43
+ super do
44
+ !read(key, options).nil?
45
+ end
46
+ end
47
+
48
+ def increment(key, amount=1)
49
+ super do
50
+ counter_key_upsert(key, amount)
51
+ end
52
+ end
53
+
54
+ def decrement(key, amount=1)
55
+ super do
56
+ counter_key_upsert(key, -amount.abs)
57
+ end
58
+ end
59
+
60
+ def clear
61
+ collection.remove
62
+ end
63
+
64
+ def stats
65
+ collection.stats
66
+ end
67
+
68
+ private
69
+ def counter_key_upsert(key, amount)
70
+ collection.update(
71
+ {:_id => key}, {
72
+ '$inc' => {:value => amount},
73
+ '$set' => {:expires_at => Time.now.utc + 1.year},
74
+ }, :upsert => true)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: UTF-8
2
+ module Bin
3
+ Version = '0.5'
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,163 @@
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
+
10
+ @collection = DB['bin_cache']
11
+ @store = Bin::Store.new(@collection)
12
+ end
13
+
14
+ let(:store) { @store }
15
+ let(:collection) { @collection }
16
+
17
+ it "has a collection" do
18
+ store.collection.should == collection
19
+ end
20
+
21
+ it "defaults expires_in to 1.year" do
22
+ store.expires_in.should == 1.year
23
+ end
24
+
25
+ it "can set default expires_in" do
26
+ Bin::Store.new(@collection, :expires_in => 5.minutes).expires_in.should == 5.minutes
27
+ end
28
+
29
+ describe "#write" do
30
+ before(:each) do
31
+ store.write('foo', 'bar')
32
+ end
33
+ let(:document) { collection.find_one(:_id => 'foo') }
34
+
35
+ it "sets _id to key" do
36
+ document['_id'].should == 'foo'
37
+ end
38
+
39
+ it "sets value key to value" do
40
+ document['value'].should == 'bar'
41
+ end
42
+
43
+ it "sets expires in to default if not provided" do
44
+ document['expires_at'].to_i.should == (Time.now.utc + 1.year).to_i
45
+ end
46
+
47
+ it "sets expires_at if expires_in provided" do
48
+ store.write('foo', 'bar', :expires_in => 5.seconds)
49
+ document['expires_at'].to_i.should == (Time.now.utc + 5.seconds).to_i
50
+ end
51
+ end
52
+
53
+ describe "#read" do
54
+ before(:each) do
55
+ store.write('foo', 'bar')
56
+ end
57
+
58
+ it "returns nil for key not found" do
59
+ store.read('non:existent:key').should be_nil
60
+ end
61
+
62
+ it "returns value key value for key found" do
63
+ store.read('foo').should == 'bar'
64
+ end
65
+
66
+ it "returns nil for existing but expired key" do
67
+ collection.save(:_id => 'foo', :value => 'bar', :expires_at => 5.seconds.ago)
68
+ store.read('foo').should be_nil
69
+ end
70
+
71
+ it "return value for existing and not expired key" do
72
+ store.write('foo', 'bar', :expires_in => 20.seconds)
73
+ store.read('foo').should == 'bar'
74
+ end
75
+ end
76
+
77
+ describe "#delete" do
78
+ before(:each) do
79
+ store.write('foo', 'bar')
80
+ end
81
+
82
+ it "delete key from cache" do
83
+ store.read('foo').should_not be_nil
84
+ store.delete('foo')
85
+ store.read('foo').should be_nil
86
+ end
87
+ end
88
+
89
+ describe "#delete_matched" do
90
+ before(:each) do
91
+ store.write('foo1', 'bar')
92
+ store.write('foo2', 'bar')
93
+ store.write('baz', 'wick')
94
+ end
95
+
96
+ it "deletes matching keys" do
97
+ store.read('foo1').should_not be_nil
98
+ store.read('foo2').should_not be_nil
99
+ store.delete_matched(/foo/)
100
+ store.read('foo1').should be_nil
101
+ store.read('foo2').should be_nil
102
+ end
103
+
104
+ it "does not delete unmatching keys" do
105
+ store.delete_matched('foo')
106
+ store.read('baz').should_not be_nil
107
+ end
108
+ end
109
+
110
+ describe "#exist?" do
111
+ before(:each) do
112
+ store.write('foo', 'bar')
113
+ end
114
+
115
+ it "returns true if key found" do
116
+ store.exist?('foo').should be_true
117
+ end
118
+
119
+ it "returns false if key not found" do
120
+ store.exist?('not:found:key').should be_false
121
+ end
122
+ end
123
+
124
+ describe "#clear" do
125
+ before(:each) do
126
+ store.write('foo', 'bar')
127
+ store.write('baz', 'wick')
128
+ end
129
+
130
+ it "clear all keys" do
131
+ collection.count.should == 2
132
+ store.clear
133
+ collection.count.should == 0
134
+ end
135
+ end
136
+
137
+ describe "#increment" do
138
+ it "increment key by amount" do
139
+ store.increment('views', 1)
140
+ store.read('views').should == 1
141
+ store.increment('views', 2)
142
+ store.read('views').should == 3
143
+ end
144
+ end
145
+
146
+ describe "#decrement" do
147
+ it "decrement key by amount" do
148
+ store.increment('views', 5)
149
+ store.decrement('views', 2)
150
+ store.read('views').should == 3
151
+ store.decrement('views', 2)
152
+ store.read('views').should == 1
153
+ end
154
+ end
155
+
156
+ describe "#stats" do
157
+ it "returns stats" do
158
+ %w[ns count size].each do |key|
159
+ store.stats.should have_key(key)
160
+ end
161
+ end
162
+ end
163
+ 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,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bin
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ version: "0.5"
9
+ platform: ruby
10
+ authors:
11
+ - John Nunemaker
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-06-02 00:00:00 -04:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: mongo
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 1
28
+ - 0
29
+ - 1
30
+ version: 1.0.1
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - <=
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 2
42
+ - 3
43
+ - 8
44
+ version: 2.3.8
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 1
56
+ - 3
57
+ - 0
58
+ version: 1.3.0
59
+ type: :development
60
+ version_requirements: *id003
61
+ description:
62
+ email:
63
+ - nunemaker@gmail.com
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files: []
69
+
70
+ files:
71
+ - lib/bin/compatibility.rb
72
+ - lib/bin/store.rb
73
+ - lib/bin/version.rb
74
+ - lib/bin.rb
75
+ - spec/bin/store_spec.rb
76
+ - spec/bin_spec.rb
77
+ - spec/helper.rb
78
+ - spec/spec.opts
79
+ - LICENSE
80
+ - Rakefile
81
+ - README.rdoc
82
+ has_rdoc: true
83
+ homepage: http://github.com/jnunemaker/bin
84
+ licenses: []
85
+
86
+ post_install_message:
87
+ rdoc_options: []
88
+
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project:
108
+ rubygems_version: 1.3.6
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: ActiveSupport MongoDB Cache store.
112
+ test_files: []
113
+