mongo_store 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,34 @@
1
+ 0.3.0 / 2010-08-30
2
+ ==================
3
+ * We have a History file now
4
+ * Converted license to Don't Be a Dick License v0.2
5
+ * Updated README
6
+ * Removed 'key' field; using '_id' instead (thanks wpiekutowski)
7
+ * Added namespace support to Rails 2 methods
8
+ * Finished Rails 3 fixes, added more specs
9
+ * Replace Entry with explicit ActiveSupport::Cache::Entry (thanks openhood)
10
+ * Updating for Rails2/Rails3 compatibility (thanks openhood)
11
+ * Fix working with Rails 3
12
+ * Updating specs for RSpec 2
13
+
14
+ 0.2.1 / 2010-04-13
15
+ ==================
16
+ * Updated for Mongo gem 0.20.1 compatibility
17
+
18
+ 0.2.0 / 2010-03-06
19
+ ==================
20
+ * Provided a proper README.
21
+ * Rewrote initialization and made options more flexible. Added #clean_expired
22
+ * Moved specs around
23
+ * Fixed error on 'nil' options being passed from Rails
24
+ * Fixing load paths for Rails
25
+ * Fixing path loading for Rails
26
+ * Embedding proper path
27
+
28
+ 0.1.0 / 2010-03-06
29
+ ==================
30
+ * All necessary methods implemented now
31
+ * Basic cache operations complete
32
+ * Collections work
33
+ * Docs started and dependencies
34
+ * Initial commit to mongo_store.
@@ -0,0 +1,113 @@
1
+ The Don't Be a Dick License
2
+ ===========================
3
+ _version 0.2_
4
+
5
+ **Project:** [MongoStore](http://github.com/SFEley/mongo_store)
6
+ **Author:** Stephen Eley (<sfeley@gmail.com>)
7
+
8
+ This is a proposed draft of the **Don't Be a Dick** license for open source projects. The purpose of this license is to permit the broadest feasible scope for reuse and modification of creative work, restricted only by the requirement that one is not a dick about it.
9
+
10
+ 1. Legal Parameters
11
+ -------------------
12
+ For legal purposes, the DBAD license is a superset of the [Apache License, Version 2.0][1] and incorporates all terms, conditions, privileges and limitations therein. The following text is a binding part of this license for this project:
13
+
14
+ > Copyright 2010 Stephen Eley
15
+
16
+ > Licensed under the Apache License, Version 2.0 (the "License");
17
+ you may not use this file except in compliance with the License.
18
+ You may obtain a copy of the License at
19
+
20
+ > <http://www.apache.org/licenses/LICENSE-2.0>
21
+
22
+ > Unless required by applicable law or agreed to in writing, software
23
+ distributed under the License is distributed on an "AS IS" BASIS,
24
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
+ See the License for the specific language governing permissions and
26
+ limitations under the License.
27
+
28
+ Nothing in the following text should be construed to inhibit, contradict, or override any part of the Apache License, Version 2.0.
29
+
30
+ 2. Definitions
31
+ --------------
32
+ The following terms and definitions shall be in effect for the rest of this document.
33
+
34
+ > **NOTE:** Singular nouns and pronouns are used throughout this License for
35
+ grammatical convenience. However, any of the terms below _may_ refer to a
36
+ collective work or group of people. If this pegs your punctiliousness, you
37
+ are directed to mentally substitute "Person _or persons_," "Dick _or
38
+ dicks,_" etc., throughout this license. Just don't tell us about it.
39
+
40
+ ### A. Project
41
+
42
+ A creative work of (software | writing | visual art | music) into which significant time and energy have been invested by people who _are not you,_ and which has been released into the world for the benefit of the general public (_including you._)
43
+
44
+ The **Project** may include, incorporate, derive from, or be inspired by other works. The Author, being a Reasonable Person, has made use of such source materials only as permitted by their own licenses or applicable law. The License you are reading applies only to those portions of the Project which are original and distinct to it. Source materials may be covered by their own licenses or conditions, and should not be assumed to have coverage under this License. (However, you are strongly encouraged not to be a dick about them either.)
45
+
46
+ ### B. Author
47
+
48
+ A person who has invested significant time and energy into the Project licensed herein. Given the Author's release of the Project to the world under a liberal license, the Author is declared a Reasonable Person (at least within this context) and inherits all attributes, freedoms, and responsibilities thereof. No other assumptions are made about the Author, nor should you make any.
49
+
50
+ ### C. Reasonable Person
51
+
52
+ A person who respects the time and energy that have been invested in the Project licensed herein, and acts accordingly. A Reasonable Person is broadly characterized as one who exercises his or her privilege to use, _not_ use, redistribute, modify, improve, worsen, review, report issues upon, participate in the community of, or ignore the work _without_ placing undue demands upon the Author. I.e., a Reasonable Person is a constituent of the majority of open source users and the population at large who are not Dicks.
53
+
54
+ ### D. Dick
55
+
56
+ A person who _does not_ respect the time and energy that have been invested in the Project, and acts to punish such effort by giving others associated with the Project -- including, but not limited to, the Author -- a hard time. A Dick is nearly always selfish, but not necessarily with deliberate intent; some Dicks are merely thoughtless. The distinguishing characteristic of a Dick is that he or she places burdens upon Reasonable People, reducing their motivation to engage in open source activities. This damping effect is a significant detriment to the Project, to open source in general, to the production of new intellectual value in the world -- and, ultimately, to the Dick himself or herself.
57
+
58
+ > **NOTE:** Despite its original gender association, the word "Dick" is used herein in a _cultural_ context and not a _genital_ context. This License has chosen to adopt the term for its linguistic force and psychological impact, and sincerely regrets any inference of sexism. For purposes of the terms and conditions contained herein, it is understood that both men and women are equally capable of being Dicks.
59
+
60
+ > (But they shouldn't be.)
61
+
62
+ 3. Permissions
63
+ --------------
64
+
65
+ The following privileges are granted explicitly and exclusively to Reasonable People. Although the Author acknowledges the practical unfeasibility of barring Dicks from enjoying the same privileges, they are nevertheless asked to refrain from any activity related to the Project _and/or_ to reconsider their behavior and stop being Dicks.
66
+
67
+ 1. You are permitted to use the Project or any component of the Project.
68
+
69
+ 2. You are permitted to redistribute the Project or any component of the Project, by itself or as part of a different work, provided that you give fair and reasonable credit back to the Author.
70
+
71
+ 3. You are permitted to change the Project for your own needs or anyone else's. You may keep your changes to yourself or submit them back to the Author or the community, as you see fit, provided you are not a Dick about it.
72
+
73
+ 4. You are permitted and encouraged to participate in any community related to the Project, or to create new communities.
74
+
75
+ 5. You are permitted to report issues or problems with the Project, and to request that they be addressed, so long as the request is made in a reasonable fashion. (This privilege does _not_ oblige the Author to respond.)
76
+
77
+ 6. You are permitted to make money from the Project. No recompense is owed to the Author unless by separate agreement, although sharing opportunities for mutual benefit is by no means discouraged.
78
+
79
+ 7. You are permitted to discuss the Project in any medium, in any positive or negative spirit, so long as criticism is not libelous nor _ad hominem._ (I.e., don't lie, and keep it about the _work_ and not the _people._)
80
+
81
+ 8. You are permitted to ignore the Project completely and make no use of it whatsoever. This right is irrevocable and absolute, and extended to Dicks and Reasonable People alike.
82
+
83
+ 4. Limitations
84
+ --------------
85
+
86
+ The following restrictions are imposed explicitly and exclusively upon Dicks. These limitations are the inverse of the above privileges and are also tautological, as the prohibited actions are those _definitive_ of Dickhood.
87
+
88
+ 1. You may not impede Reasonable People from exercising their privilege to use, redistribute, change, participate in, profit from, discuss, or ignore the Project.
89
+
90
+ 2. You may not withhold the Author's credit for the Project, nor otherwise present the work of anyone else as your own.
91
+
92
+ 3. You may not hold the Author responsible for any use or abuse of the Project by you or anyone else.
93
+
94
+ 4. You may not troll, flame, nor dumb down any community associated with the Project.
95
+
96
+ 5. Barring separate agreements, you may not _demand_ any time or attention on the part of the Author nor anyone else in the community. You may not hold the Author personally accountable for any issues you discover nor otherwise spread your own problems to other people.
97
+
98
+ 6. You may not attempt to _compel_ time nor money from the Author nor any other community member by any means, including but not limited to legal action, intimidation, or annoyance.
99
+
100
+ 7. You may not engage in _ad hominem_ (i.e. personal) attacks or criticism of the Author in the course of criticizing the Project.
101
+
102
+ 8. You may not impede the absolute and irrevocable privilege of the Author and other members of the community to ignore you.
103
+
104
+ 5. Use of This License
105
+ ----------------------
106
+ The Don't Be a Dick License is released under the terms of the Don't Be a Dick License. Projects released under this License should remain under the License, and the terms of the License may not be modified by anyone other than the Project's original Author.
107
+
108
+ If you wish to make use of the License for your own open work, you may do so without asking permission, provided said work is truly your own, truly open, and you are truly not a Dick. You may modify the terms of the License to suit your own needs, but are strongly advised to annotate said changes. Modifications may not reduce the freedoms granted to Reasonable People as described in Section 3.
109
+
110
+ Reasonable People are _invited,_ but not compelled, to visit the Web site at <http://dbad-license.org> and browse or add their project to the repository of works released under the License.
111
+
112
+
113
+ [1]: http://apache.org/licenses/LICENSE-2.0
@@ -1,6 +1,7 @@
1
1
  # MongoStore
2
2
 
3
- It's **ActiveSupport::Cache::MongoStore** -- a [MongoDB](http://mongodb.org)-based provider for the standard Rails cache mechanism. With an emphasis on fast writes and a memory-mapped architecture, Mongo is well-suited to caching. This gem aims to give you what the ubiquitous **MemCacheStore** does, but with Mongo's persistence. (And without having to put a second RAM devourer in an environment already running Mongo.)
3
+ It's **ActiveSupport::Cache::MongoStore** -- a [MongoDB](http://mongodb.org)-based provider for the standard Rails 2 or Rails 3 cache mechanism. With an emphasis on fast writes and a memory-mapped architecture, Mongo is well-suited to caching. This gem aims to give you what the ubiquitous **MemCacheStore** does, but with Mongo's persistence. (And without having to put a second RAM devourer in an environment already running Mongo.)
4
+
4
5
 
5
6
  ## Getting Started
6
7
 
@@ -32,15 +33,16 @@ We don't have a separate option for connecting to a different server. If you do
32
33
  The following hash options are recognized on initialization:
33
34
 
34
35
  * `:db` - A Mongo::DB object or the name of one to create. Defaults to **rails_cache**.
35
- * `:create_index` - By default, we create an index on the _key_ and _expires_ fields. Set to **false** to override.
36
+ * `:create_index` - By default, we create an index on the *_id* and *expires* fields for fast returns on cache misses. Set to **false** to override.
36
37
  * `:expires_in` - The global length of time a cache key remains valid. Defaults to 1 year. Can also be set on individual cache writes.
38
+ * `:namespace` - Set this if you want different applications to share the same Mongo collection without key collisions. (Namespacing is baked into Rails 3, but MongoStore implements it manually for Rails 2 as well.)
37
39
 
38
40
  ## Other Goodness
39
41
 
40
42
  MongoStore is a drop-in caching store and doesn't require any special treatment. The only extra behavior on top of what you get from ActiveSupport::Cache::Store is as follows:
41
43
 
42
44
  ### :expires_in option on the #write method
43
- This is the same behavior as the option in the MemCacheStore. Specify a number of seconds or an ActiveSupport helper equivalent, e.g.: `:expires_in => 5.minutes`. Keys past their expiration date are not returned on reads.
45
+ This was built into all stores in Rails 3. In Rails 2, we implement it with same behavior as the option in MemCacheStore. Specify a number of seconds or an ActiveSupport helper equivalent, e.g.: `:expires_in => 5.minutes`. Keys past their expiration date are not returned on reads.
44
46
 
45
47
  _**NOTE:** This behavior is fairly dumb and uses `Time.now` on the application side. If you have a number of app servers hitting one database and their times aren't in sync, expect unwarranted cache misses._
46
48
 
@@ -62,8 +64,6 @@ Empties the cache. The moral equivalent of `Rails.cache.delete_matched(/.*/)` bu
62
64
 
63
65
  * This code and specs were written for Ruby 1.9.1. I tried to make sure it works fine for you anachronists (Ruby 1.8), but didn't confirm it. Please register an issue if I forgot your quaint historical syntax. I also didn't test it in JRuby, Rubinius, IronRuby, or your roommate's HP-48 calculator.
64
66
 
65
- * Likewise, this was written for Rails 2.3.5. I have not tried to run it in Rails 3 yet, which is still in beta at the time of this writing. I don't even know if Rails 3 uses the same caching approach. It probably caches using pure energy or something, and removes carbon from the atmosphere at the same time.
66
-
67
67
  * I am optimistic about performance but have not benchmarked it, apart from "It's faster than not using a cache."
68
68
 
69
69
  ## Support
@@ -81,6 +81,9 @@ You can also [check out my podcast](http://escapepod.org) if you like science fi
81
81
 
82
82
  And Have Fun.
83
83
 
84
- ## Copyright
84
+ ## License
85
+
86
+ This project is licensed under the [Don't Be a Dick License](http://dbad-license.org), version 0.2, and is copyright
87
+ 2010 by Stephen Eley. See the [LICENSE.markdown](http://github.com/SFEley/mongo_store/blob/master/LICENSE.markdown)
88
+ file for elaboration on not being a dick. (But you probably already know.)
85
89
 
86
- Copyright (c) 2010 Stephen Eley. See LICENSE for details.
data/Rakefile CHANGED
@@ -10,9 +10,9 @@ begin
10
10
  gem.email = "sfeley@gmail.com"
11
11
  gem.homepage = "http://github.com/SFEley/mongo_store"
12
12
  gem.authors = ["Stephen Eley"]
13
- gem.add_dependency "mongo", ">= 0.18.3"
13
+ gem.add_dependency "mongo", ">= 1.0"
14
14
  gem.add_dependency "activesupport", ">= 2.2"
15
- gem.add_development_dependency "rspec", ">= 1.2.9"
15
+ gem.add_development_dependency "rspec", ">= 1.3"
16
16
  gem.add_development_dependency "mocha", ">= 0.9"
17
17
 
18
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.3.0
@@ -1,25 +1,134 @@
1
1
  require 'active_support'
2
2
  require 'mongo'
3
3
 
4
+ module MongoStore
5
+ module Cache
6
+ module Rails2
7
+ attr_reader :options
8
+
9
+ # Inserts the value into the cache collection or updates the existing value. The value must be a valid
10
+ # MongoDB type. An *:expires_in* option may be provided, as with MemCacheStore. If one is _not_
11
+ # provided, a default expiration of 1 day is used.
12
+ def write(key, value, local_options=nil)
13
+ super
14
+ opts = local_options ? options.merge(local_options) : options
15
+ expires = Time.now + opts[:expires_in]
16
+ collection.update({'_id' => namespaced_key(key, opts)}, {'$set' => {'value' => value, 'expires' => expires}}, :upsert => true)
17
+ end
18
+
19
+ # Reads the value from the cache collection.
20
+ def read(key, local_options=nil)
21
+ super
22
+ opts = local_options ? options.merge(local_options) : options
23
+ if doc = collection.find_one('_id' => namespaced_key(key, opts), 'expires' => {'$gt' => Time.now})
24
+ doc['value']
25
+ end
26
+ end
27
+
28
+ # Takes the specified value out of the collection.
29
+ def delete(key, local_options=nil)
30
+ super
31
+ opts = local_options ? options.merge(local_options) : options
32
+ collection.remove({'_id' => namespaced_key(key,opts)})
33
+ end
34
+
35
+
36
+ # Takes the value matching the pattern out of the collection.
37
+ def delete_matched(key, local_options=nil)
38
+ super
39
+ opts = local_options ? options.merge(local_options) : options
40
+ collection.remove({'_id' => key_matcher(key,opts)})
41
+ end
42
+
43
+
44
+ protected
45
+
46
+ # Lifted from Rails 3 ActiveSupport::Cache::Store
47
+ def namespaced_key(key, options)
48
+ namespace = options[:namespace] if options
49
+ prefix = namespace.is_a?(Proc) ? namespace.call : namespace
50
+ key = "#{prefix}:#{key}" if prefix
51
+ key
52
+ end
53
+
54
+ # Lifted from Rails 3 ActiveSupport::Cache::Store
55
+ def key_matcher(pattern, options)
56
+ prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
57
+ if prefix
58
+ source = pattern.source
59
+ if source.start_with?('^')
60
+ source = source[1, source.length]
61
+ else
62
+ source = ".*#{source[0, source.length]}"
63
+ end
64
+ Regexp.new("^#{Regexp.escape(prefix)}:#{source}", pattern.options)
65
+ else
66
+ pattern
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ module Rails3
73
+ def write_entry(key, entry, options)
74
+ expires = Time.now + options[:expires_in]
75
+ value = entry.value
76
+ value = value.to_mongo if value.respond_to? :to_mongo
77
+ begin
78
+ collection.update({'_id' => key}, {'$set' => {'value' => value, 'expires' => expires}}, :upsert => true)
79
+ rescue BSON::InvalidDocument
80
+ value = value.to_s and retry unless value.is_a? String
81
+ end
82
+ end
83
+ def read_entry(key, options=nil)
84
+ doc = collection.find_one('_id' => key, 'expires' => {'$gt' => Time.now})
85
+ ActiveSupport::Cache::Entry.new(doc['value']) if doc
86
+ end
87
+ def delete_entry(key, options=nil)
88
+ collection.remove({'_id' => key})
89
+ end
90
+ def delete_matched(pattern, options=nil)
91
+ options = merged_options(options)
92
+ instrument(:delete_matched, pattern.inspect) do
93
+ matcher = key_matcher(pattern, options) # Handles namespacing with regexes
94
+ delete_entry(matcher, options)
95
+ end
96
+ end
97
+ end
98
+
99
+ module Store
100
+ rails3 = defined?(::Rails) && ::Rails.version =~ /^3\./
101
+ include rails3 ? Rails3 : Rails2
102
+
103
+ def expires_in
104
+ options[:expires_in]
105
+ end
106
+
107
+ def expires_in=(val)
108
+ options[:expires_in] = val
109
+ end
110
+ end
111
+ end
112
+ end
113
+
4
114
  module ActiveSupport
5
115
  module Cache
6
116
  class MongoStore < Store
7
- attr_reader :options
8
- attr_accessor :expires_in
117
+ include ::MongoStore::Cache::Store
9
118
 
10
119
  # Returns a MongoDB cache store. Can take either a Mongo::Collection object or a collection name.
11
120
  # If neither is provided, a collection named "rails_cache" is created.
12
121
  #
13
122
  # An options hash may also be provided with the following options:
14
123
  #
15
- # * :expires_in - The default expiration period for cached objects. If not provided, defaults to 1 year.
124
+ # * :expires_in - The default expiration period for cached objects. If not provided, defaults to 1 day.
16
125
  # * :db - Either a Mongo::DB object or a database name. Not used if a Mongo::Collection object is passed. Otherwise defaults to MongoMapper.database (if MongoMapper is used in the app) or else creates a DB named "rails_cache".
17
126
  # * :create_index - Whether to index the key and expiration date on the collection. Defaults to true. Not used if a Mongo::Collection object is passed.
18
127
  def initialize(collection = nil, options = nil)
19
128
  @options = {
20
129
  :collection_name => 'rails_cache',
21
130
  :db_name => 'rails_cache',
22
- :expires_in => 1.year,
131
+ :expires_in => 86400, # That's 1 day in seconds
23
132
  :create_index => true
24
133
  }
25
134
  # @options.merge!(options) if options
@@ -37,10 +146,6 @@ module ActiveSupport
37
146
  end
38
147
 
39
148
  @options.merge!(options) if options.is_a?(Hash)
40
-
41
- # Set the expiration time
42
- self.expires_in = @options[:expires_in]
43
- super()
44
149
  end
45
150
 
46
151
  # Returns the MongoDB collection described in the options to .new (or else the default 'rails_cache' one.)
@@ -63,32 +168,6 @@ module ActiveSupport
63
168
  collection.remove
64
169
  end
65
170
 
66
- # Inserts the value into the cache collection or updates the existing value. The value must be a valid
67
- # MongoDB type. An *:expires_in* option may be provided, as with MemCacheStore. If one is _not_
68
- # provided, a default expiration of 1 year is used.
69
- def write(key, value, options=nil)
70
- super
71
- expires = Time.now + ((options && options[:expires_in]) || expires_in)
72
- collection.update({'key' => key}, {'$set' => {'value' => value, 'expires' => expires}}, :upsert => true)
73
- end
74
-
75
- # Reads the value from the cache collection.
76
- def read(key, options=nil)
77
- super
78
- if doc = collection.find_one('key' => key, 'expires' => {'$gt' => Time.now})
79
- doc['value']
80
- end
81
- end
82
-
83
- # Takes the specified value out of the collection.
84
- def delete(key, options=nil)
85
- super
86
- collection.remove({'key' => key})
87
- end
88
-
89
- # With MongoDB, there's no difference between querying on an exact value or a regex. Beautiful, huh?
90
- alias_method :delete_matched, :delete
91
-
92
171
  private
93
172
  def mongomapper?
94
173
  Kernel.const_defined?(:MongoMapper) && MongoMapper.respond_to?(:database) && MongoMapper.database
@@ -106,7 +185,7 @@ module ActiveSupport
106
185
  end
107
186
  end
108
187
  coll = db.create_collection(options[:collection_name])
109
- coll.create_index([['key',Mongo::ASCENDING], ['expires',Mongo::DESCENDING]]) if options[:create_index]
188
+ coll.create_index([['_id',Mongo::ASCENDING], ['expires',Mongo::DESCENDING]]) if options[:create_index]
110
189
  coll
111
190
  end
112
191
 
@@ -5,21 +5,23 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongo_store}
8
- s.version = "0.2.1"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Stephen Eley"]
12
- s.date = %q{2010-04-13}
12
+ s.date = %q{2010-08-30}
13
13
  s.description = %q{It's ActiveSupport::Cache::MongoStore -- a MongoDB-based provider for the standard Rails cache mechanism. With an emphasis on fast writes and a memory-mapped architecture, Mongo is well-suited to caching. This gem aims to give you what the ubiquitous MemCacheStore does, but with Mongo's persistence. (And without having to put a second RAM devourer in an environment already running Mongo.)}
14
14
  s.email = %q{sfeley@gmail.com}
15
15
  s.extra_rdoc_files = [
16
- "LICENSE",
16
+ "LICENSE.markdown",
17
17
  "README.markdown"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
21
  ".gitignore",
22
- "LICENSE",
22
+ ".rspec",
23
+ "History.markdown",
24
+ "LICENSE.markdown",
23
25
  "README.markdown",
24
26
  "Rakefile",
25
27
  "VERSION",
@@ -33,7 +35,7 @@ Gem::Specification.new do |s|
33
35
  s.homepage = %q{http://github.com/SFEley/mongo_store}
34
36
  s.rdoc_options = ["--charset=UTF-8"]
35
37
  s.require_paths = ["lib"]
36
- s.rubygems_version = %q{1.3.6}
38
+ s.rubygems_version = %q{1.3.7}
37
39
  s.summary = %q{Rails caching for MongoDB}
38
40
  s.test_files = [
39
41
  "spec/active_support/cache/mongo_store_spec.rb",
@@ -44,21 +46,21 @@ Gem::Specification.new do |s|
44
46
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
47
  s.specification_version = 3
46
48
 
47
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
- s.add_runtime_dependency(%q<mongo>, [">= 0.18.3"])
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<mongo>, [">= 1.0"])
49
51
  s.add_runtime_dependency(%q<activesupport>, [">= 2.2"])
50
- s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
52
+ s.add_development_dependency(%q<rspec>, [">= 1.3"])
51
53
  s.add_development_dependency(%q<mocha>, [">= 0.9"])
52
54
  else
53
- s.add_dependency(%q<mongo>, [">= 0.18.3"])
55
+ s.add_dependency(%q<mongo>, [">= 1.0"])
54
56
  s.add_dependency(%q<activesupport>, [">= 2.2"])
55
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
57
+ s.add_dependency(%q<rspec>, [">= 1.3"])
56
58
  s.add_dependency(%q<mocha>, [">= 0.9"])
57
59
  end
58
60
  else
59
- s.add_dependency(%q<mongo>, [">= 0.18.3"])
61
+ s.add_dependency(%q<mongo>, [">= 1.0"])
60
62
  s.add_dependency(%q<activesupport>, [">= 2.2"])
61
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
63
+ s.add_dependency(%q<rspec>, [">= 1.3"])
62
64
  s.add_dependency(%q<mocha>, [">= 0.9"])
63
65
  end
64
66
  end
@@ -69,9 +69,9 @@ module ActiveSupport
69
69
  store.collection.should_not be_nil
70
70
  end
71
71
 
72
- it "defaults to an expiration of 1 year" do
72
+ it "defaults to an expiration of 1 day" do
73
73
  store = ActiveSupport::Cache.lookup_store(:mongo_store)
74
- store.expires_in.should == 1.year
74
+ store.expires_in.should == 1.day
75
75
  end
76
76
 
77
77
  it "can override expiration time with the :expires_in option" do
@@ -105,11 +105,11 @@ module ActiveSupport
105
105
 
106
106
  it "can write values" do
107
107
  @store.write('fnord', 'I am vaguely disturbed.')
108
- @store.collection.find_one(:key => 'fnord')['value'].should == "I am vaguely disturbed."
108
+ @store.collection.find_one('_id' => 'fnord')['value'].should == "I am vaguely disturbed."
109
109
  end
110
110
 
111
111
  it "can read values" do
112
- @store.collection.insert({:key => 'yoo', :value => 'yar', :expires => 1.year.from_now})
112
+ @store.collection.insert({'_id' => 'yoo', :value => 'yar', :expires => (Time.now + 10)})
113
113
  @store.read('yoo').should == 'yar'
114
114
  end
115
115
 
@@ -172,6 +172,63 @@ module ActiveSupport
172
172
  @store.clear
173
173
  @store.collection.count.should == 0
174
174
  end
175
+ describe "namespacing" do
176
+ before(:each) do
177
+ @store.options[:namespace] = 'ns1'
178
+ @store.write 'foo', 'bar'
179
+ @store.write 'too', 'tar'
180
+ @store.write 'foz', 'baz'
181
+ @store.write 'foo', 'yar', :namespace => 'ns2'
182
+ @store.write 'too', 'car', :namespace => 'ns2'
183
+ @store.write 'foz', 'bat', :namespace => 'ns2'
184
+ end
185
+
186
+ it "uses the default namespace" do
187
+ @store.collection.find_one('_id' => /ns1.*foo/)['value'].should == "bar"
188
+ end
189
+
190
+ it "can override the namespace" do
191
+ @store.collection.find_one('_id' => /ns2.*foo/)['value'].should == "yar"
192
+ end
193
+
194
+ it "can have different values in different namespaces" do
195
+ @store.read('foo').should == 'bar'
196
+ @store.read('foo', :namespace => 'ns2').should == 'yar'
197
+ end
198
+
199
+ it "deletes from the default namespace" do
200
+ @store.delete('foo')
201
+ @store.read('foo').should be_nil
202
+ @store.read('foo', :namespace => 'ns2').should == 'yar'
203
+ end
204
+
205
+ it "deletes from an overridden namespace" do
206
+ @store.delete('foo', :namespace => 'ns2')
207
+ @store.read('foo').should == 'bar'
208
+ @store.read('foo', :namespace => 'ns2').should be_nil
209
+ end
210
+
211
+ it "deletes matching patterns from the default namespace" do
212
+ @store.delete_matched(/oo/)
213
+ @store.read('foo').should be_nil
214
+ @store.read('too').should be_nil
215
+ @store.read('foz').should == 'baz'
216
+ @store.read('foo', :namespace => 'ns2').should == 'yar'
217
+ @store.read('too', :namespace => 'ns2').should == 'car'
218
+ @store.read('foz', :namespace => 'ns2').should == 'bat'
219
+ end
220
+
221
+ it "deletes matching patterns from the overridden namespace" do
222
+ @store.delete_matched(/oo/, :namespace => "ns2")
223
+ @store.read('foo').should == 'bar'
224
+ @store.read('too').should == 'tar'
225
+ @store.read('foz').should == 'baz'
226
+ @store.read('foo', :namespace => 'ns2').should be_nil
227
+ @store.read('too', :namespace => 'ns2').should be_nil
228
+ @store.read('foz', :namespace => 'ns2').should == 'bat'
229
+ end
230
+
231
+ end
175
232
 
176
233
  after(:each) do
177
234
  @store.collection.remove # Clear our records
@@ -2,10 +2,18 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'mongo'
4
4
  require 'mongo_store'
5
- require 'spec'
6
- require 'spec/autorun'
5
+ require 'rspec' # RSpec 2
6
+ require 'rspec/autorun'
7
7
  require 'mocha'
8
8
 
9
- Spec::Runner.configure do |config|
9
+ # Fake out Rails 3 -- for Rails 2 testing, run with a gemset with activesupport ~ 2.3
10
+ module Rails
11
+ def self.version
12
+ ActiveSupport::Cache.const_defined?(:Entry) ? '3.0.0' : '2.3.8'
13
+ end
14
+ end
15
+
16
+
17
+ RSpec.configure do |config|
10
18
  config.mock_with :mocha
11
19
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 2
8
- - 1
9
- version: 0.2.1
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Stephen Eley
@@ -14,27 +14,28 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-13 00:00:00 -04:00
17
+ date: 2010-08-30 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: mongo
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
24
25
  requirements:
25
26
  - - ">="
26
27
  - !ruby/object:Gem::Version
27
28
  segments:
29
+ - 1
28
30
  - 0
29
- - 18
30
- - 3
31
- version: 0.18.3
31
+ version: "1.0"
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: activesupport
36
36
  prerelease: false
37
37
  requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
38
39
  requirements:
39
40
  - - ">="
40
41
  - !ruby/object:Gem::Version
@@ -48,20 +49,21 @@ dependencies:
48
49
  name: rspec
49
50
  prerelease: false
50
51
  requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
51
53
  requirements:
52
54
  - - ">="
53
55
  - !ruby/object:Gem::Version
54
56
  segments:
55
57
  - 1
56
- - 2
57
- - 9
58
- version: 1.2.9
58
+ - 3
59
+ version: "1.3"
59
60
  type: :development
60
61
  version_requirements: *id003
61
62
  - !ruby/object:Gem::Dependency
62
63
  name: mocha
63
64
  prerelease: false
64
65
  requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
65
67
  requirements:
66
68
  - - ">="
67
69
  - !ruby/object:Gem::Version
@@ -78,12 +80,14 @@ executables: []
78
80
  extensions: []
79
81
 
80
82
  extra_rdoc_files:
81
- - LICENSE
83
+ - LICENSE.markdown
82
84
  - README.markdown
83
85
  files:
84
86
  - .document
85
87
  - .gitignore
86
- - LICENSE
88
+ - .rspec
89
+ - History.markdown
90
+ - LICENSE.markdown
87
91
  - README.markdown
88
92
  - Rakefile
89
93
  - VERSION
@@ -103,6 +107,7 @@ rdoc_options:
103
107
  require_paths:
104
108
  - lib
105
109
  required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
106
111
  requirements:
107
112
  - - ">="
108
113
  - !ruby/object:Gem::Version
@@ -110,6 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
115
  - 0
111
116
  version: "0"
112
117
  required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
113
119
  requirements:
114
120
  - - ">="
115
121
  - !ruby/object:Gem::Version
@@ -119,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
125
  requirements: []
120
126
 
121
127
  rubyforge_project:
122
- rubygems_version: 1.3.6
128
+ rubygems_version: 1.3.7
123
129
  signing_key:
124
130
  specification_version: 3
125
131
  summary: Rails caching for MongoDB
data/LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2010 Stephen Eley
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.