mongomodel 0.4.5 → 0.4.6
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/Appraisals +9 -4
- data/gemfiles/rails-3.1.gemfile +2 -2
- data/gemfiles/rails-3.2.gemfile +2 -2
- data/gemfiles/rails-4.gemfile +11 -0
- data/lib/mongomodel.rb +3 -0
- data/lib/mongomodel/concerns/activemodel.rb +4 -0
- data/lib/mongomodel/concerns/map_reduce.rb +51 -0
- data/lib/mongomodel/concerns/observing.rb +35 -0
- data/lib/mongomodel/document.rb +2 -2
- data/lib/mongomodel/document/scopes.rb +1 -1
- data/lib/mongomodel/embedded_document.rb +3 -0
- data/lib/mongomodel/railtie.rb +18 -1
- data/lib/mongomodel/support/instrumented_collection.rb +6 -0
- data/lib/mongomodel/support/mongo_options.rb +6 -2
- data/lib/mongomodel/support/mongo_order.rb +1 -1
- data/lib/mongomodel/support/scope.rb +7 -2
- data/lib/mongomodel/support/scope/spawn_methods.rb +2 -0
- data/lib/mongomodel/support/types/time.rb +6 -4
- data/lib/mongomodel/version.rb +1 -1
- data/mongomodel.gemspec +2 -2
- data/spec/mongomodel/attributes/store_spec.rb +4 -4
- data/spec/mongomodel/concerns/attribute_methods/multi_parameter_assignment_spec.rb +1 -1
- data/spec/mongomodel/concerns/map_reduce_spec.rb +140 -0
- data/spec/mongomodel/concerns/observing_spec.rb +32 -0
- data/spec/mongomodel/support/scope_spec.rb +7 -1
- data/spec/spec_helper.rb +3 -1
- metadata +112 -120
data/Appraisals
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
appraise "rails-3.1" do
|
2
|
-
gem "activesupport", "3.1.
|
3
|
-
gem "activemodel", "3.1.
|
2
|
+
gem "activesupport", "3.1.8"
|
3
|
+
gem "activemodel", "3.1.8"
|
4
4
|
end
|
5
5
|
|
6
6
|
appraise "rails-3.2" do
|
7
|
-
gem "activesupport",
|
8
|
-
gem "activemodel",
|
7
|
+
gem "activesupport", "3.2.8"
|
8
|
+
gem "activemodel", "3.2.8"
|
9
|
+
end
|
10
|
+
|
11
|
+
appraise "rails-4" do
|
12
|
+
gem "activesupport", :git => "https://github.com/rails/rails.git"
|
13
|
+
gem "activemodel", :git => "https://github.com/rails/rails.git"
|
9
14
|
end
|
data/gemfiles/rails-3.1.gemfile
CHANGED
data/gemfiles/rails-3.2.gemfile
CHANGED
@@ -5,7 +5,7 @@ source "http://rubygems.org"
|
|
5
5
|
gem "appraisal", "~> 0.3.6"
|
6
6
|
gem "bson_ext", "~> 1.5"
|
7
7
|
gem "tzinfo"
|
8
|
-
gem "activesupport",
|
9
|
-
gem "activemodel",
|
8
|
+
gem "activesupport", "3.2.8"
|
9
|
+
gem "activemodel", "3.2.8"
|
10
10
|
|
11
11
|
gemspec :path=>"../"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "appraisal", "~> 0.3.6"
|
6
|
+
gem "bson_ext", "~> 1.5"
|
7
|
+
gem "tzinfo"
|
8
|
+
gem "activesupport", :git=>"https://github.com/rails/rails.git"
|
9
|
+
gem "activemodel", :git=>"https://github.com/rails/rails.git"
|
10
|
+
|
11
|
+
gemspec :path=>"../"
|
data/lib/mongomodel.rb
CHANGED
@@ -22,6 +22,8 @@ module MongoModel
|
|
22
22
|
autoload :Translation, 'mongomodel/concerns/translation'
|
23
23
|
autoload :Validations, 'mongomodel/concerns/validations'
|
24
24
|
autoload :Callbacks, 'mongomodel/concerns/callbacks'
|
25
|
+
autoload :Observing, 'mongomodel/concerns/observing'
|
26
|
+
autoload :Observer, 'mongomodel/concerns/observing'
|
25
27
|
autoload :Serialization, 'mongomodel/concerns/serialization'
|
26
28
|
autoload :Logging, 'mongomodel/concerns/logging'
|
27
29
|
autoload :Timestamps, 'mongomodel/concerns/timestamps'
|
@@ -29,6 +31,7 @@ module MongoModel
|
|
29
31
|
autoload :RecordStatus, 'mongomodel/concerns/record_status'
|
30
32
|
autoload :AbstractClass, 'mongomodel/concerns/abstract_class'
|
31
33
|
autoload :DocumentParent, 'mongomodel/concerns/document_parent'
|
34
|
+
autoload :MapReduce, 'mongomodel/concerns/map_reduce'
|
32
35
|
autoload :ActiveModelCompatibility, 'mongomodel/concerns/activemodel'
|
33
36
|
|
34
37
|
autoload :Reference, 'mongomodel/support/reference'
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MongoModel::MapReduce
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
include MongoModel::DocumentExtensions::Scopes
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :parent_collection
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def from_mongo(attrs)
|
12
|
+
new(attrs['_id'], attrs['value'])
|
13
|
+
end
|
14
|
+
|
15
|
+
def cached
|
16
|
+
from(collection_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def database
|
20
|
+
parent_collection.db
|
21
|
+
end
|
22
|
+
|
23
|
+
def collection
|
24
|
+
parent_collection.map_reduce(map_function, reduce_function, map_reduce_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def collection_name
|
28
|
+
@_collection_name || default_collection_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def collection_name=(name)
|
32
|
+
@_collection_name = name
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_collection_name
|
36
|
+
[parent_collection.name, name.demodulize.tableize.gsub(/\//, '.')].join("._")
|
37
|
+
end
|
38
|
+
|
39
|
+
def map_function
|
40
|
+
raise NotImplementedError, "map_function is not implemented"
|
41
|
+
end
|
42
|
+
|
43
|
+
def reduce_function
|
44
|
+
raise NotImplementedError, "reduce_function is not implemented"
|
45
|
+
end
|
46
|
+
|
47
|
+
def map_reduce_options
|
48
|
+
{ :out => collection_name }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module MongoModel
|
2
|
+
module Observing
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include ActiveModel::Observing
|
5
|
+
end
|
6
|
+
|
7
|
+
class Observer < ActiveModel::Observer
|
8
|
+
protected
|
9
|
+
def observed_classes
|
10
|
+
klasses = super
|
11
|
+
klasses + klasses.map { |klass| klass.descendants }.flatten
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_observer!(klass)
|
15
|
+
super
|
16
|
+
define_callbacks(klass)
|
17
|
+
end
|
18
|
+
|
19
|
+
def define_callbacks(klass)
|
20
|
+
observer = self
|
21
|
+
observer_name = observer.class.name.underscore.gsub('/', '__')
|
22
|
+
|
23
|
+
MongoModel::Callbacks::CALLBACKS.each do |callback|
|
24
|
+
next unless respond_to?(callback)
|
25
|
+
callback_meth = :"_notify_#{observer_name}_for_#{callback}"
|
26
|
+
unless klass.respond_to?(callback_meth)
|
27
|
+
klass.send(:define_method, callback_meth) do |&block|
|
28
|
+
observer.update(callback, self, &block)
|
29
|
+
end
|
30
|
+
klass.send(callback, callback_meth)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/mongomodel/document.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'active_support/core_ext/class/
|
1
|
+
require 'active_support/core_ext/class/attribute'
|
2
2
|
require 'active_support/core_ext/hash/reverse_merge'
|
3
3
|
require 'active_support/core_ext/hash/deep_merge'
|
4
4
|
require 'active_support/core_ext/string/inflections'
|
@@ -22,7 +22,7 @@ module MongoModel
|
|
22
22
|
|
23
23
|
self.abstract_class = true
|
24
24
|
|
25
|
-
|
25
|
+
class_attribute :per_page
|
26
26
|
self.per_page = 20
|
27
27
|
end
|
28
28
|
end
|
@@ -10,6 +10,7 @@ module MongoModel
|
|
10
10
|
include Translation
|
11
11
|
include Validations
|
12
12
|
include Callbacks
|
13
|
+
include Observing
|
13
14
|
|
14
15
|
include Associations
|
15
16
|
|
@@ -46,3 +47,5 @@ module MongoModel
|
|
46
47
|
self.abstract_class = true
|
47
48
|
end
|
48
49
|
end
|
50
|
+
|
51
|
+
ActiveSupport::run_load_hooks(:mongomodel, MongoModel::EmbeddedDocument)
|
data/lib/mongomodel/railtie.rb
CHANGED
@@ -8,7 +8,9 @@ module MongoModel
|
|
8
8
|
config.action_dispatch.rescue_responses.merge!(rescue_responses)
|
9
9
|
end
|
10
10
|
|
11
|
-
config.app_generators.orm :mongo_model, :migration => false
|
11
|
+
config.app_generators.orm :mongo_model, :migration => false
|
12
|
+
|
13
|
+
config.mongomodel = ActiveSupport::OrderedOptions.new
|
12
14
|
|
13
15
|
rake_tasks do
|
14
16
|
load "mongomodel/tasks/database.rake"
|
@@ -54,5 +56,20 @@ module MongoModel
|
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
59
|
+
|
60
|
+
initializer "mongomodel.observers" do |app|
|
61
|
+
MongoModel::EmbeddedDocument.observers = app.config.mongomodel.observers || []
|
62
|
+
end
|
63
|
+
|
64
|
+
# Lazily initialize observer instances
|
65
|
+
config.after_initialize do
|
66
|
+
ActiveSupport.on_load(:mongomodel) do
|
67
|
+
instantiate_observers
|
68
|
+
|
69
|
+
ActionDispatch::Reloader.to_prepare do
|
70
|
+
MongoModel::EmbeddedDocument.instantiate_observers
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
57
74
|
end
|
58
75
|
end
|
@@ -109,6 +109,12 @@ module MongoModel
|
|
109
109
|
collection.distinct(key, query)
|
110
110
|
end
|
111
111
|
end
|
112
|
+
|
113
|
+
def map_reduce(map, reduce, options={})
|
114
|
+
instrument("map_reduce(#{options.inspect})") do
|
115
|
+
collection.map_reduce(map, reduce, options)
|
116
|
+
end
|
117
|
+
end
|
112
118
|
|
113
119
|
private
|
114
120
|
def method_missing(method, *args, &block)
|
@@ -28,7 +28,7 @@ module MongoModel
|
|
28
28
|
(options[:conditions] || {}).each do |k, v|
|
29
29
|
key = k.is_a?(MongoOperator) ? k.field : k
|
30
30
|
|
31
|
-
if property = @model.properties[key]
|
31
|
+
if @model.respond_to?(:properties) && property = @model.properties[key]
|
32
32
|
key = property.as
|
33
33
|
value = v.is_a?(Array) ? v.map { |i| property.to_query(i) } : property.to_query(v);
|
34
34
|
else
|
@@ -69,9 +69,13 @@ module MongoModel
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def add_type_to_selector
|
72
|
-
if
|
72
|
+
if use_type_selector?
|
73
73
|
selector['_type'] = { '$in' => @model.type_selector }
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
def use_type_selector?
|
78
|
+
@model.respond_to?(:use_type_selector?) && @model.use_type_selector? && selector['_type'].nil?
|
79
|
+
end
|
76
80
|
end
|
77
81
|
end
|
@@ -163,8 +163,7 @@ module MongoModel
|
|
163
163
|
|
164
164
|
private
|
165
165
|
def _find
|
166
|
-
|
167
|
-
|
166
|
+
ensure_indexes!
|
168
167
|
selector, options = MongoOptions.new(klass, finder_options).to_a
|
169
168
|
collection.find(selector, options)
|
170
169
|
end
|
@@ -194,5 +193,11 @@ module MongoModel
|
|
194
193
|
{ :id.in => ids.map { |id| id.to_s } }
|
195
194
|
end
|
196
195
|
end
|
196
|
+
|
197
|
+
def ensure_indexes!
|
198
|
+
if klass.respond_to?(:indexes_initialized?) && !klass.indexes_initialized?
|
199
|
+
klass.ensure_indexes!
|
200
|
+
end
|
201
|
+
end
|
197
202
|
end
|
198
203
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/time/conversions'
|
2
|
+
require 'active_support/core_ext/time/zones'
|
2
3
|
require 'active_support/core_ext/string/conversions'
|
3
4
|
|
4
5
|
module MongoModel
|
@@ -9,12 +10,13 @@ module MongoModel
|
|
9
10
|
when ::Array
|
10
11
|
base = ::Time.zone ? ::Time.zone : ::Time
|
11
12
|
base.local(*value)
|
13
|
+
when ::String
|
14
|
+
base = ::Time.zone ? ::Time.zone : ::Time
|
15
|
+
cast(base.parse(value))
|
12
16
|
when ::Hash
|
13
17
|
cast("#{value[:date]} #{value[:time]}")
|
14
|
-
when ::String
|
15
|
-
cast(::Time.parse(value))
|
16
18
|
else
|
17
|
-
time = value.to_time
|
19
|
+
time = value.to_time.in_time_zone
|
18
20
|
time.change(:usec => (time.usec / 1000.0).floor * 1000)
|
19
21
|
end
|
20
22
|
rescue
|
@@ -26,7 +28,7 @@ module MongoModel
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def from_mongo(value)
|
29
|
-
value.
|
31
|
+
value.in_time_zone if value
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
data/lib/mongomodel/version.rb
CHANGED
data/mongomodel.gemspec
CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.required_rubygems_version = ">= 1.3.6"
|
15
15
|
s.rubyforge_project = "mongomodel"
|
16
16
|
|
17
|
-
s.add_dependency "activesupport", "
|
18
|
-
s.add_dependency "activemodel", "
|
17
|
+
s.add_dependency "activesupport", ">= 3.1"
|
18
|
+
s.add_dependency "activemodel", ">= 3.1"
|
19
19
|
s.add_dependency "mongo", "~> 1.5"
|
20
20
|
s.add_dependency "will_paginate", "~> 2.3.15"
|
21
21
|
|
@@ -132,13 +132,13 @@ module MongoModel
|
|
132
132
|
},
|
133
133
|
:time =>
|
134
134
|
{
|
135
|
-
Time.local(2008, 5, 14, 1, 2, 3, 123456) => Time.local(2008, 5, 14, 1, 2, 3, 123000),
|
136
|
-
Date.civil(2009, 11, 15) => Time.local(2009, 11, 15, 0, 0, 0, 0),
|
135
|
+
Time.local(2008, 5, 14, 1, 2, 3, 123456) => Time.local(2008, 5, 14, 1, 2, 3, 123000).in_time_zone,
|
136
|
+
Date.civil(2009, 11, 15) => Time.local(2009, 11, 15, 0, 0, 0, 0).in_time_zone,
|
137
137
|
"Sat Jan 01 20:15:01.123456 UTC 2000" => Time.utc(2000, 1, 1, 20, 15, 1, 123000),
|
138
|
-
"2009/3/4" => Time.local(2009, 3, 4, 0, 0, 0, 0),
|
138
|
+
"2009/3/4" => Time.zone.local(2009, 3, 4, 0, 0, 0, 0),
|
139
139
|
"09:34" => lambda { |t| t.hour == 9 && t.min == 34 },
|
140
140
|
"5:21pm" => lambda { |t| t.hour == 17 && t.min == 21 },
|
141
|
-
{ :date => "2005-11-04", :time => "4:55pm" } => Time.local(2005, 11, 4, 16, 55, 0),
|
141
|
+
{ :date => "2005-11-04", :time => "4:55pm" } => Time.zone.local(2005, 11, 4, 16, 55, 0),
|
142
142
|
nil => nil
|
143
143
|
},
|
144
144
|
:datetime =>
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module MongoModel
|
4
|
+
describe "MapReduce" do
|
5
|
+
describe "counting tags" do
|
6
|
+
# This example is extracted from the Counting Tags pattern in the
|
7
|
+
# MongoDB Cookbook: http://cookbook.mongodb.org/patterns/count_tags/
|
8
|
+
|
9
|
+
define_class(:Article, Document) do
|
10
|
+
property :tags, Collection[String]
|
11
|
+
end
|
12
|
+
|
13
|
+
define_class(:Tag, Struct.new(:name, :count)) do
|
14
|
+
include MongoModel::MapReduce
|
15
|
+
|
16
|
+
self.parent_collection = Article.collection
|
17
|
+
|
18
|
+
def initialize(name, count)
|
19
|
+
super(name, count.to_i)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.map_function
|
23
|
+
<<-MAP
|
24
|
+
function() {
|
25
|
+
if (!this.tags) { return; }
|
26
|
+
|
27
|
+
for (i in this.tags) {
|
28
|
+
emit(this.tags[i], 1);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
MAP
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.reduce_function
|
35
|
+
<<-REDUCE
|
36
|
+
function(key, values) {
|
37
|
+
var count = 0;
|
38
|
+
|
39
|
+
for (i in values) {
|
40
|
+
count += values[i];
|
41
|
+
}
|
42
|
+
|
43
|
+
return count;
|
44
|
+
}
|
45
|
+
REDUCE
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
specify "tag comparison" do
|
50
|
+
Tag.new("Tag 1", 1).should == Tag.new("Tag 1", 1)
|
51
|
+
Tag.new("Tag 2", 1).should_not == Tag.new("Tag 1", 1)
|
52
|
+
Tag.new("Tag 1", 1).should_not == Tag.new("Tag 1", 2)
|
53
|
+
end
|
54
|
+
|
55
|
+
before do
|
56
|
+
Article.create!(:tags => ["Tag 1", "Tag 2"])
|
57
|
+
Article.create!(:tags => ["Tag 2"])
|
58
|
+
Article.create!(:tags => ["Tag 3"])
|
59
|
+
end
|
60
|
+
|
61
|
+
it "has a default collection name based on the parent collection" do
|
62
|
+
Tag.collection_name.should == "articles._tags"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "stores the result in a named collection" do
|
66
|
+
Tag.collection.name.should == Tag.collection_name
|
67
|
+
end
|
68
|
+
|
69
|
+
it "allows use of scope methods" do
|
70
|
+
Tag.all.should == [Tag.new("Tag 1", 1), Tag.new("Tag 2", 2), Tag.new("Tag 3", 1)]
|
71
|
+
Tag.order(:value.desc).first.should == Tag.new("Tag 2", 2)
|
72
|
+
Tag.where(:value.gt => 1).should == [Tag.new("Tag 2", 2)]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "loads previously computed results" do
|
76
|
+
expected = Tag.all
|
77
|
+
Article.create!(:tags => ["Tag 1"])
|
78
|
+
Tag.cached.should == expected
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "pivot data" do
|
83
|
+
# This example is similar to the Pivot Data pattern in the
|
84
|
+
# MongoDB Cookbook: http://cookbook.mongodb.org/patterns/pivot/
|
85
|
+
|
86
|
+
define_class(:Actor, Document) do
|
87
|
+
property :name, String
|
88
|
+
property :movies, Collection[String]
|
89
|
+
end
|
90
|
+
|
91
|
+
define_class(:Movie, Struct.new(:name, :actors)) do
|
92
|
+
include MongoModel::MapReduce
|
93
|
+
|
94
|
+
self.parent_collection = Actor.collection
|
95
|
+
|
96
|
+
def self.from_mongo(attrs)
|
97
|
+
new(attrs['_id'], attrs['value']['actors'].sort)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.map_function
|
101
|
+
<<-MAP
|
102
|
+
function() {
|
103
|
+
for (i in this.movies) {
|
104
|
+
emit(this.movies[i], { actors: [this.name] });
|
105
|
+
}
|
106
|
+
}
|
107
|
+
MAP
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.reduce_function
|
111
|
+
<<-REDUCE
|
112
|
+
function(key, values) {
|
113
|
+
var result = { actors: [] };
|
114
|
+
|
115
|
+
for (i in values) {
|
116
|
+
result.actors = result.actors.concat(values[i].actors);
|
117
|
+
}
|
118
|
+
|
119
|
+
return result;
|
120
|
+
}
|
121
|
+
REDUCE
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
before do
|
126
|
+
Actor.create!(:name => "Richard Gere", :movies => ['Pretty Woman', 'Runaway Bride', 'Chicago'])
|
127
|
+
Actor.create!(:name => "Julia Roberts", :movies => ['Pretty Woman', 'Runaway Bride', 'Erin Brockovich'])
|
128
|
+
end
|
129
|
+
|
130
|
+
it "pivots data" do
|
131
|
+
Movie.all.should include(
|
132
|
+
Movie.new("Pretty Woman", ["Julia Roberts", "Richard Gere"]),
|
133
|
+
Movie.new("Runaway Bride", ["Julia Roberts", "Richard Gere"]),
|
134
|
+
Movie.new("Chicago", ["Richard Gere"]),
|
135
|
+
Movie.new("Erin Brockovich", ["Julia Roberts"])
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module MongoModel
|
4
|
+
specs_for(Document) do
|
5
|
+
describe "observing" do
|
6
|
+
define_class(:TestDocument, described_class)
|
7
|
+
define_class(:TestObserver, Observer) do
|
8
|
+
observe :test_document
|
9
|
+
|
10
|
+
attr_accessor :callback
|
11
|
+
|
12
|
+
def after_save(model)
|
13
|
+
@callback.call(model) unless @callback.nil?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
subject { TestDocument.new }
|
18
|
+
|
19
|
+
it "should have an #instance method to access the observer singleton" do
|
20
|
+
TestObserver.instance.should eq(TestObserver.instance)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should invoke the TestObserver singleton's after_save method after saving" do
|
24
|
+
callback = stub
|
25
|
+
callback.should_receive(:call).with(subject)
|
26
|
+
|
27
|
+
TestObserver.instance.callback = callback
|
28
|
+
subject.save
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1061,10 +1061,12 @@ module MongoModel
|
|
1061
1061
|
end
|
1062
1062
|
|
1063
1063
|
describe "#merge" do
|
1064
|
+
let(:on_load_proc) { proc {} }
|
1064
1065
|
let(:merged) do
|
1065
1066
|
basic_scope.where(:date.gt => timestamp-1.year).
|
1066
1067
|
order(:date.desc).
|
1067
|
-
select(:date)
|
1068
|
+
select(:date).
|
1069
|
+
on_load(&on_load_proc)
|
1068
1070
|
end
|
1069
1071
|
let(:result) { subject.merge(merged) }
|
1070
1072
|
|
@@ -1085,6 +1087,10 @@ module MongoModel
|
|
1085
1087
|
result.select_values.should == [:author, :published, :date]
|
1086
1088
|
end
|
1087
1089
|
|
1090
|
+
it "should preserve on load proc" do
|
1091
|
+
result.on_load_proc.should == on_load_proc
|
1092
|
+
end
|
1093
|
+
|
1088
1094
|
context "merged scope has offset value" do
|
1089
1095
|
let(:merged) { basic_scope.offset(10) }
|
1090
1096
|
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,9 @@ require 'mongomodel'
|
|
8
8
|
# Require spec helpers
|
9
9
|
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
|
10
10
|
|
11
|
+
require 'active_support/time'
|
12
|
+
Time.zone = "Australia/Melbourne"
|
13
|
+
|
11
14
|
RSpec.configure do |config|
|
12
15
|
include SpecsFor
|
13
16
|
include DefineClass
|
@@ -18,6 +21,5 @@ RSpec.configure do |config|
|
|
18
21
|
|
19
22
|
config.before(:each) do
|
20
23
|
MongoModel.database.collections.each { |c| c.drop rescue c.remove }
|
21
|
-
Time.zone = "Australia/Adelaide"
|
22
24
|
end
|
23
25
|
end
|
metadata
CHANGED
@@ -1,140 +1,136 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongomodel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.6
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 4
|
9
|
-
- 5
|
10
|
-
version: 0.4.5
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Sam Pohlenz
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
prerelease: false
|
22
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
-
none: false
|
24
|
-
requirements:
|
25
|
-
- - ~>
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
hash: 5
|
28
|
-
segments:
|
29
|
-
- 3
|
30
|
-
- 1
|
31
|
-
version: "3.1"
|
32
|
-
version_requirements: *id001
|
12
|
+
date: 2012-09-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
33
15
|
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.1'
|
34
22
|
type: :runtime
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
23
|
prerelease: false
|
37
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
25
|
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
|
44
|
-
- 3
|
45
|
-
- 1
|
46
|
-
version: "3.1"
|
47
|
-
version_requirements: *id002
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.1'
|
30
|
+
- !ruby/object:Gem::Dependency
|
48
31
|
name: activemodel
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.1'
|
49
38
|
type: :runtime
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
39
|
prerelease: false
|
52
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
41
|
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
|
59
|
-
- 1
|
60
|
-
- 5
|
61
|
-
version: "1.5"
|
62
|
-
version_requirements: *id003
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.1'
|
46
|
+
- !ruby/object:Gem::Dependency
|
63
47
|
name: mongo
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.5'
|
64
54
|
type: :runtime
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
55
|
prerelease: false
|
67
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
57
|
none: false
|
69
|
-
requirements:
|
58
|
+
requirements:
|
70
59
|
- - ~>
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
|
74
|
-
- 2
|
75
|
-
- 3
|
76
|
-
- 15
|
77
|
-
version: 2.3.15
|
78
|
-
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.5'
|
62
|
+
- !ruby/object:Gem::Dependency
|
79
63
|
name: will_paginate
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.3.15
|
80
70
|
type: :runtime
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
71
|
prerelease: false
|
83
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
84
73
|
none: false
|
85
|
-
requirements:
|
86
|
-
- -
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
|
89
|
-
|
90
|
-
- 1
|
91
|
-
- 0
|
92
|
-
- 0
|
93
|
-
version: 1.0.0
|
94
|
-
version_requirements: *id005
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.3.15
|
78
|
+
- !ruby/object:Gem::Dependency
|
95
79
|
name: bundler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.0.0
|
96
86
|
type: :development
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
87
|
prerelease: false
|
99
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
89
|
none: false
|
101
|
-
requirements:
|
102
|
-
- -
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
|
105
|
-
|
106
|
-
- 2
|
107
|
-
- 8
|
108
|
-
version: "2.8"
|
109
|
-
version_requirements: *id006
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.0.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
110
95
|
name: rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '2.8'
|
111
102
|
type: :development
|
112
|
-
- !ruby/object:Gem::Dependency
|
113
103
|
prerelease: false
|
114
|
-
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
115
105
|
none: false
|
116
|
-
requirements:
|
106
|
+
requirements:
|
117
107
|
- - ~>
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
|
120
|
-
|
121
|
-
- 0
|
122
|
-
- 5
|
123
|
-
- 0
|
124
|
-
version: 0.5.0
|
125
|
-
version_requirements: *id007
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '2.8'
|
110
|
+
- !ruby/object:Gem::Dependency
|
126
111
|
name: guard-rspec
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.5.0
|
127
118
|
type: :development
|
128
|
-
|
129
|
-
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.5.0
|
126
|
+
description: MongoModel is a MongoDB ORM for Ruby/Rails similar to ActiveRecord and
|
127
|
+
DataMapper.
|
128
|
+
email:
|
130
129
|
- sam@sampohlenz.com
|
131
130
|
executables: []
|
132
|
-
|
133
131
|
extensions: []
|
134
|
-
|
135
132
|
extra_rdoc_files: []
|
136
|
-
|
137
|
-
files:
|
133
|
+
files:
|
138
134
|
- .gitignore
|
139
135
|
- Appraisals
|
140
136
|
- Gemfile
|
@@ -145,6 +141,7 @@ files:
|
|
145
141
|
- bin/console
|
146
142
|
- gemfiles/rails-3.1.gemfile
|
147
143
|
- gemfiles/rails-3.2.gemfile
|
144
|
+
- gemfiles/rails-4.gemfile
|
148
145
|
- lib/mongomodel.rb
|
149
146
|
- lib/mongomodel/attributes/mongo.rb
|
150
147
|
- lib/mongomodel/attributes/store.rb
|
@@ -171,6 +168,8 @@ files:
|
|
171
168
|
- lib/mongomodel/concerns/callbacks.rb
|
172
169
|
- lib/mongomodel/concerns/document_parent.rb
|
173
170
|
- lib/mongomodel/concerns/logging.rb
|
171
|
+
- lib/mongomodel/concerns/map_reduce.rb
|
172
|
+
- lib/mongomodel/concerns/observing.rb
|
174
173
|
- lib/mongomodel/concerns/pretty_inspect.rb
|
175
174
|
- lib/mongomodel/concerns/properties.rb
|
176
175
|
- lib/mongomodel/concerns/record_status.rb
|
@@ -253,6 +252,8 @@ files:
|
|
253
252
|
- spec/mongomodel/concerns/attributes_spec.rb
|
254
253
|
- spec/mongomodel/concerns/callbacks_spec.rb
|
255
254
|
- spec/mongomodel/concerns/logging_spec.rb
|
255
|
+
- spec/mongomodel/concerns/map_reduce_spec.rb
|
256
|
+
- spec/mongomodel/concerns/observing_spec.rb
|
256
257
|
- spec/mongomodel/concerns/pretty_inspect_spec.rb
|
257
258
|
- spec/mongomodel/concerns/properties_spec.rb
|
258
259
|
- spec/mongomodel/concerns/serialization/json_serialization_spec.rb
|
@@ -295,38 +296,29 @@ files:
|
|
295
296
|
- spec/support/models.rb
|
296
297
|
homepage: http://www.mongomodel.org
|
297
298
|
licenses: []
|
298
|
-
|
299
299
|
post_install_message:
|
300
300
|
rdoc_options: []
|
301
|
-
|
302
|
-
require_paths:
|
301
|
+
require_paths:
|
303
302
|
- lib
|
304
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
303
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
305
304
|
none: false
|
306
|
-
requirements:
|
307
|
-
- -
|
308
|
-
- !ruby/object:Gem::Version
|
309
|
-
|
310
|
-
segments:
|
305
|
+
requirements:
|
306
|
+
- - ! '>='
|
307
|
+
- !ruby/object:Gem::Version
|
308
|
+
version: '0'
|
309
|
+
segments:
|
311
310
|
- 0
|
312
|
-
|
313
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
311
|
+
hash: -4172752819017214767
|
312
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
314
313
|
none: false
|
315
|
-
requirements:
|
316
|
-
- -
|
317
|
-
- !ruby/object:Gem::Version
|
318
|
-
hash: 23
|
319
|
-
segments:
|
320
|
-
- 1
|
321
|
-
- 3
|
322
|
-
- 6
|
314
|
+
requirements:
|
315
|
+
- - ! '>='
|
316
|
+
- !ruby/object:Gem::Version
|
323
317
|
version: 1.3.6
|
324
318
|
requirements: []
|
325
|
-
|
326
319
|
rubyforge_project: mongomodel
|
327
|
-
rubygems_version: 1.8.
|
320
|
+
rubygems_version: 1.8.24
|
328
321
|
signing_key:
|
329
322
|
specification_version: 3
|
330
323
|
summary: MongoDB ORM for Ruby/Rails
|
331
324
|
test_files: []
|
332
|
-
|