mongoid_collection_snapshot 0.0.1 → 0.1.0
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/README.md +31 -3
- data/VERSION +1 -1
- data/lib/mongoid_collection_snapshot.rb +11 -5
- data/mongoid_collection_snapshot.gemspec +10 -8
- data/spec/models/multi_collection_snapshot.rb +14 -0
- data/spec/mongoid/collection_snapshot_spec.rb +39 -2
- metadata +16 -16
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Mongoid Collection Snapshot
|
2
2
|
===========================
|
3
3
|
|
4
|
-
Easy
|
4
|
+
Easy maintenance of collections of processed data in MongoDB with the Mongoid ODM.
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
Quick example:
|
7
|
+
--------------
|
8
8
|
|
9
9
|
Suppose that you have a Mongoid model called `Artwork`, stored
|
10
10
|
in a MongoDB collection called `artworks` and the underlying documents
|
@@ -78,3 +78,31 @@ method `build`, which populates the collection snapshot and any indexes you need
|
|
78
78
|
By default, mongoid_collection_snapshot maintains the most recent two snapshots
|
79
79
|
computed any given time.
|
80
80
|
|
81
|
+
Other features
|
82
|
+
--------------
|
83
|
+
|
84
|
+
You can maintain multiple collections atomically within the same snapshot by
|
85
|
+
passing unique collection identifiers to ``collection_snaphot`` when you call it
|
86
|
+
in your build or query methods:
|
87
|
+
|
88
|
+
class ArtistStats
|
89
|
+
include Mongoid::CollectionSnapshot
|
90
|
+
|
91
|
+
def build
|
92
|
+
# ...
|
93
|
+
# define map/reduce for average and max aggregations
|
94
|
+
# ...
|
95
|
+
Artwork.collection.map_reduce(map_avg, reduce_avg, :out => collection_snapshot('average'))
|
96
|
+
Artwork.collection.map_reduce(map_max, reduce_max, :out => collection_snapshot('max'))
|
97
|
+
end
|
98
|
+
|
99
|
+
def average_price(artist)
|
100
|
+
doc = collection_snapshot('average').findOne({'_id.artist': artist})
|
101
|
+
doc['value']['sum']/doc['value']['count']
|
102
|
+
end
|
103
|
+
|
104
|
+
def max_price(artist)
|
105
|
+
doc = collection_snapshot('max').findOne({'_id.artist': artist})
|
106
|
+
doc['value']['max']
|
107
|
+
end
|
108
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
@@ -15,7 +15,7 @@ module Mongoid::CollectionSnapshot
|
|
15
15
|
|
16
16
|
before_save :build
|
17
17
|
after_save :ensure_at_most_two_instances_exist
|
18
|
-
before_destroy :
|
18
|
+
before_destroy :drop_snapshot_collections
|
19
19
|
end
|
20
20
|
|
21
21
|
module ClassMethods
|
@@ -24,12 +24,18 @@ module Mongoid::CollectionSnapshot
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def collection_snapshot
|
28
|
-
|
27
|
+
def collection_snapshot(name=nil)
|
28
|
+
if name
|
29
|
+
Mongoid.master.collection("#{self.collection.name}.#{name}.#{workspace_slug}")
|
30
|
+
else
|
31
|
+
Mongoid.master.collection("#{self.collection.name}.#{workspace_slug}")
|
32
|
+
end
|
29
33
|
end
|
30
34
|
|
31
|
-
def
|
32
|
-
|
35
|
+
def drop_snapshot_collections
|
36
|
+
Mongoid.master.collections.each do |collection|
|
37
|
+
collection.drop if collection.name =~ /^#{self.collection.name}\.([^\.]+\.)?#{workspace_slug}$/
|
38
|
+
end
|
33
39
|
end
|
34
40
|
|
35
41
|
# Since we should always be using the latest instance of this class, this method is
|
@@ -4,14 +4,14 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.0
|
7
|
+
s.name = "mongoid_collection_snapshot"
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aaron Windsor"]
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
12
|
+
s.date = "2012-01-24"
|
13
|
+
s.description = "Easy maintenence of collections of processed data in MongoDB with the Mongoid ODM"
|
14
|
+
s.email = "aaron.windsor@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.txt",
|
17
17
|
"README.md"
|
@@ -26,17 +26,19 @@ Gem::Specification.new do |s|
|
|
26
26
|
"mongoid_collection_snapshot.gemspec",
|
27
27
|
"spec/models/artwork.rb",
|
28
28
|
"spec/models/average_artist_price.rb",
|
29
|
+
"spec/models/multi_collection_snapshot.rb",
|
29
30
|
"spec/mongoid/collection_snapshot_spec.rb",
|
30
31
|
"spec/spec_helper.rb"
|
31
32
|
]
|
32
|
-
s.homepage =
|
33
|
+
s.homepage = "http://github.com/aaw/mongoid_collection_snapshot"
|
33
34
|
s.licenses = ["MIT"]
|
34
35
|
s.require_paths = ["lib"]
|
35
|
-
s.rubygems_version =
|
36
|
-
s.summary =
|
36
|
+
s.rubygems_version = "1.8.10"
|
37
|
+
s.summary = "Easy maintenence of collections of processed data in MongoDB with the Mongoid ODM"
|
37
38
|
s.test_files = [
|
38
39
|
"spec/models/artwork.rb",
|
39
40
|
"spec/models/average_artist_price.rb",
|
41
|
+
"spec/models/multi_collection_snapshot.rb",
|
40
42
|
"spec/mongoid/collection_snapshot_spec.rb",
|
41
43
|
"spec/spec_helper.rb"
|
42
44
|
]
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class MultiCollectionSnapshot
|
2
|
+
include Mongoid::CollectionSnapshot
|
3
|
+
|
4
|
+
def build
|
5
|
+
collection_snapshot('foo').insert({'name' => 'foo!'})
|
6
|
+
collection_snapshot('bar').insert({'name' => 'bar!'})
|
7
|
+
collection_snapshot('baz').insert({'name' => 'baz!'})
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_names
|
11
|
+
['foo', 'bar', 'baz'].map{ |x| collection_snapshot(x).find_one['name'] }.join('')
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module Mongoid
|
4
4
|
describe CollectionSnapshot do
|
5
5
|
|
6
|
-
context "creating a snapshot" do
|
6
|
+
context "creating a basic snapshot" do
|
7
7
|
|
8
8
|
let!(:flowers) { Artwork.create(:name => 'Flowers', :artist => 'Andy Warhol', :price => 3000000) }
|
9
9
|
let!(:guns) { Artwork.create(:name => 'Guns', :artist => 'Andy Warhol', :price => 1000000) }
|
@@ -12,11 +12,13 @@ module Mongoid
|
|
12
12
|
it "returns nil if no snapshot has been created" do
|
13
13
|
AverageArtistPrice.latest.should be_nil
|
14
14
|
end
|
15
|
+
|
15
16
|
it "runs the build method on creation" do
|
16
17
|
snapshot = AverageArtistPrice.create
|
17
18
|
snapshot.average_price('Andy Warhol').should == 2000000
|
18
19
|
snapshot.average_price('Damien Hirst').should == 1500000
|
19
20
|
end
|
21
|
+
|
20
22
|
it "returns the most recent snapshot through the latest methods" do
|
21
23
|
first = AverageArtistPrice.create
|
22
24
|
first.should == AverageArtistPrice.latest
|
@@ -31,12 +33,47 @@ module Mongoid
|
|
31
33
|
third = AverageArtistPrice.create
|
32
34
|
AverageArtistPrice.latest.should == third
|
33
35
|
end
|
36
|
+
|
34
37
|
it "should only maintain at most two of the latest snapshots to support its calculations" do
|
38
|
+
AverageArtistPrice.create
|
35
39
|
10.times do
|
36
40
|
AverageArtistPrice.create
|
37
|
-
AverageArtistPrice.count.should
|
41
|
+
AverageArtistPrice.count.should == 2
|
38
42
|
end
|
39
43
|
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "creating a snapshot containing multiple collections" do
|
48
|
+
|
49
|
+
it "populates several collections and allows them to be queried" do
|
50
|
+
MultiCollectionSnapshot.latest.should be_nil
|
51
|
+
10.times { MultiCollectionSnapshot.create }
|
52
|
+
MultiCollectionSnapshot.latest.get_names.should == "foo!bar!baz!"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "safely cleans up all collections used by the snapshot" do
|
56
|
+
# Create some collections with names close to the snapshots we'll create
|
57
|
+
Mongoid.master["#{MultiCollectionSnapshot.collection.name}.do.not_delete"].insert({'a' => 1})
|
58
|
+
Mongoid.master["#{MultiCollectionSnapshot.collection.name}.snapshorty"].insert({'a' => 1})
|
59
|
+
Mongoid.master["#{MultiCollectionSnapshot.collection.name}.hello.1"].insert({'a' => 1})
|
60
|
+
|
61
|
+
MultiCollectionSnapshot.create
|
62
|
+
before_create = Mongoid.master.collections.map{ |c| c.name }
|
63
|
+
before_create.length.should > 0
|
64
|
+
|
65
|
+
sleep(1)
|
66
|
+
MultiCollectionSnapshot.create
|
67
|
+
after_create = Mongoid.master.collections.map{ |c| c.name }
|
68
|
+
collections_created = (after_create - before_create).sort
|
69
|
+
collections_created.length.should == 3
|
70
|
+
|
71
|
+
MultiCollectionSnapshot.latest.destroy
|
72
|
+
after_destroy = Mongoid.master.collections.map{ |c| c.name }
|
73
|
+
collections_destroyed = (after_create - after_destroy).sort
|
74
|
+
collections_created.should == collections_destroyed
|
75
|
+
end
|
76
|
+
|
40
77
|
end
|
41
78
|
|
42
79
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_collection_snapshot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
default_executable:
|
12
|
+
date: 2012-01-24 00:00:00.000000000Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: mongoid_slug
|
17
|
-
requirement: &
|
16
|
+
requirement: &2156103400 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,10 +21,10 @@ dependencies:
|
|
22
21
|
version: 0.8.2
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *2156103400
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: mongoid
|
28
|
-
requirement: &
|
27
|
+
requirement: &2156101560 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ~>
|
@@ -33,10 +32,10 @@ dependencies:
|
|
33
32
|
version: 2.0.0
|
34
33
|
type: :development
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *2156101560
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
37
|
name: bson_ext
|
39
|
-
requirement: &
|
38
|
+
requirement: &2156099780 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
41
|
- - ~>
|
@@ -44,10 +43,10 @@ dependencies:
|
|
44
43
|
version: 1.3.0
|
45
44
|
type: :development
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *2156099780
|
48
47
|
- !ruby/object:Gem::Dependency
|
49
48
|
name: rspec
|
50
|
-
requirement: &
|
49
|
+
requirement: &2156095320 !ruby/object:Gem::Requirement
|
51
50
|
none: false
|
52
51
|
requirements:
|
53
52
|
- - ~>
|
@@ -55,10 +54,10 @@ dependencies:
|
|
55
54
|
version: 2.5.0
|
56
55
|
type: :development
|
57
56
|
prerelease: false
|
58
|
-
version_requirements: *
|
57
|
+
version_requirements: *2156095320
|
59
58
|
- !ruby/object:Gem::Dependency
|
60
59
|
name: jeweler
|
61
|
-
requirement: &
|
60
|
+
requirement: &2156093080 !ruby/object:Gem::Requirement
|
62
61
|
none: false
|
63
62
|
requirements:
|
64
63
|
- - ~>
|
@@ -66,7 +65,7 @@ dependencies:
|
|
66
65
|
version: 1.5.2
|
67
66
|
type: :development
|
68
67
|
prerelease: false
|
69
|
-
version_requirements: *
|
68
|
+
version_requirements: *2156093080
|
70
69
|
description: Easy maintenence of collections of processed data in MongoDB with the
|
71
70
|
Mongoid ODM
|
72
71
|
email: aaron.windsor@gmail.com
|
@@ -85,9 +84,9 @@ files:
|
|
85
84
|
- mongoid_collection_snapshot.gemspec
|
86
85
|
- spec/models/artwork.rb
|
87
86
|
- spec/models/average_artist_price.rb
|
87
|
+
- spec/models/multi_collection_snapshot.rb
|
88
88
|
- spec/mongoid/collection_snapshot_spec.rb
|
89
89
|
- spec/spec_helper.rb
|
90
|
-
has_rdoc: true
|
91
90
|
homepage: http://github.com/aaw/mongoid_collection_snapshot
|
92
91
|
licenses:
|
93
92
|
- MIT
|
@@ -103,7 +102,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
102
|
version: '0'
|
104
103
|
segments:
|
105
104
|
- 0
|
106
|
-
hash:
|
105
|
+
hash: -1729910918776026621
|
107
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
107
|
none: false
|
109
108
|
requirements:
|
@@ -112,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
111
|
version: '0'
|
113
112
|
requirements: []
|
114
113
|
rubyforge_project:
|
115
|
-
rubygems_version: 1.
|
114
|
+
rubygems_version: 1.8.10
|
116
115
|
signing_key:
|
117
116
|
specification_version: 3
|
118
117
|
summary: Easy maintenence of collections of processed data in MongoDB with the Mongoid
|
@@ -120,5 +119,6 @@ summary: Easy maintenence of collections of processed data in MongoDB with the M
|
|
120
119
|
test_files:
|
121
120
|
- spec/models/artwork.rb
|
122
121
|
- spec/models/average_artist_price.rb
|
122
|
+
- spec/models/multi_collection_snapshot.rb
|
123
123
|
- spec/mongoid/collection_snapshot_spec.rb
|
124
124
|
- spec/spec_helper.rb
|