mongo_mapper 0.11.0 → 0.11.1
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/lib/mongo_mapper.rb +1 -0
- data/lib/mongo_mapper/connection.rb +7 -4
- data/lib/mongo_mapper/document.rb +1 -0
- data/lib/mongo_mapper/embedded_document.rb +1 -0
- data/lib/mongo_mapper/extensions/time.rb +1 -2
- data/lib/mongo_mapper/plugins/associations/base.rb +5 -1
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +25 -1
- data/lib/mongo_mapper/plugins/associations/single_association.rb +1 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +4 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +1 -0
- data/lib/mongo_mapper/plugins/inspect.rb +1 -1
- data/lib/mongo_mapper/plugins/modifiers.rb +37 -25
- data/lib/mongo_mapper/plugins/querying.rb +4 -11
- data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +9 -3
- data/lib/mongo_mapper/plugins/touch.rb +18 -0
- data/lib/mongo_mapper/version.rb +1 -1
- data/test/functional/associations/test_many_documents_proxy.rb +62 -0
- data/test/functional/test_modifiers.rb +147 -96
- data/test/functional/test_querying.rb +37 -0
- data/test/functional/test_timestamps.rb +5 -5
- data/test/functional/test_touch.rb +125 -0
- data/test/unit/associations/test_base.rb +10 -0
- data/test/unit/test_extensions.rb +4 -4
- data/test/unit/test_inspect.rb +20 -0
- data/test/unit/test_mongo_mapper.rb +10 -0
- data/test/unit/test_time_zones.rb +5 -0
- metadata +16 -16
data/lib/mongo_mapper.rb
CHANGED
@@ -56,6 +56,7 @@ module MongoMapper
|
|
56
56
|
autoload :Timestamps, 'mongo_mapper/plugins/timestamps'
|
57
57
|
autoload :Userstamps, 'mongo_mapper/plugins/userstamps'
|
58
58
|
autoload :Validations, 'mongo_mapper/plugins/validations'
|
59
|
+
autoload :Touch, 'mongo_mapper/plugins/touch'
|
59
60
|
|
60
61
|
module Associations
|
61
62
|
autoload :Base, 'mongo_mapper/plugins/associations/base'
|
@@ -3,6 +3,11 @@ require 'uri'
|
|
3
3
|
|
4
4
|
module MongoMapper
|
5
5
|
module Connection
|
6
|
+
@@connection = nil
|
7
|
+
@@database = nil
|
8
|
+
@@database_name = nil
|
9
|
+
@@config = nil
|
10
|
+
|
6
11
|
# @api public
|
7
12
|
def connection
|
8
13
|
@@connection ||= Mongo::Connection.new
|
@@ -26,9 +31,7 @@ module MongoMapper
|
|
26
31
|
|
27
32
|
# @api public
|
28
33
|
def database
|
29
|
-
if @@database_name.blank?
|
30
|
-
raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
|
31
|
-
end
|
34
|
+
return nil if @@database_name.blank?
|
32
35
|
|
33
36
|
@@database ||= MongoMapper.connection.db(@@database_name)
|
34
37
|
end
|
@@ -44,7 +47,7 @@ module MongoMapper
|
|
44
47
|
|
45
48
|
# @api private
|
46
49
|
def config_for_environment(environment)
|
47
|
-
env = config[environment] || {}
|
50
|
+
env = config[environment.to_s] || {}
|
48
51
|
return env if env['uri'].blank?
|
49
52
|
|
50
53
|
uri = URI.parse(env['uri'])
|
@@ -29,6 +29,7 @@ module MongoMapper
|
|
29
29
|
include Plugins::Serialization
|
30
30
|
include Plugins::Timestamps
|
31
31
|
include Plugins::Userstamps
|
32
|
+
include Plugins::Touch
|
32
33
|
include Plugins::Validations
|
33
34
|
include Plugins::EmbeddedCallbacks
|
34
35
|
include Plugins::Callbacks # for now callbacks needs to be after validations
|
@@ -8,8 +8,7 @@ module MongoMapper
|
|
8
8
|
else
|
9
9
|
time_class = ::Time.try(:zone).present? ? ::Time.zone : ::Time
|
10
10
|
time = value.is_a?(::Time) ? value : time_class.parse(value.to_s)
|
11
|
-
|
12
|
-
at(time.to_i).utc if time
|
11
|
+
at(time.to_f).utc if time # ensure milliseconds are preserved with to_f (issue #308)
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
@@ -6,7 +6,7 @@ module MongoMapper
|
|
6
6
|
attr_reader :name, :options, :query_options
|
7
7
|
|
8
8
|
# Options that should not be considered MongoDB query options/criteria
|
9
|
-
AssociationOptions = [:as, :class, :class_name, :dependent, :extend, :foreign_key, :in, :polymorphic, :autosave]
|
9
|
+
AssociationOptions = [:as, :class, :class_name, :dependent, :extend, :foreign_key, :in, :polymorphic, :autosave, :touch]
|
10
10
|
|
11
11
|
def initialize(name, options={}, &extension)
|
12
12
|
@name, @options, @query_options, @original_options = name.to_sym, {}, {}, options
|
@@ -39,6 +39,10 @@ module MongoMapper
|
|
39
39
|
klass.embeddable?
|
40
40
|
end
|
41
41
|
|
42
|
+
def touch?
|
43
|
+
!!@options[:touch]
|
44
|
+
end
|
45
|
+
|
42
46
|
def type_key_name
|
43
47
|
"_type"
|
44
48
|
end
|
@@ -18,12 +18,36 @@ module MongoMapper
|
|
18
18
|
def setup(model)
|
19
19
|
model.key foreign_key, ObjectId unless model.key?(foreign_key)
|
20
20
|
super
|
21
|
+
add_touch_callbacks if touch?
|
21
22
|
end
|
22
23
|
|
23
24
|
def autosave?
|
24
25
|
options.fetch(:autosave, false)
|
25
26
|
end
|
27
|
+
|
28
|
+
def add_touch_callbacks
|
29
|
+
name = self.name
|
30
|
+
method_name = "belongs_to_touch_after_save_or_destroy_for_#{name}"
|
31
|
+
touch = options.fetch(:touch)
|
32
|
+
|
33
|
+
@model.send(:define_method, method_name) do
|
34
|
+
record = send(name)
|
35
|
+
|
36
|
+
unless record.nil?
|
37
|
+
if touch == true
|
38
|
+
record.touch
|
39
|
+
else
|
40
|
+
record.touch(touch)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@model.after_save(method_name)
|
46
|
+
@model.after_touch(method_name)
|
47
|
+
@model.after_destroy(method_name)
|
48
|
+
|
49
|
+
end
|
26
50
|
end
|
27
51
|
end
|
28
52
|
end
|
29
|
-
end
|
53
|
+
end
|
@@ -7,7 +7,7 @@ module MongoMapper
|
|
7
7
|
def inspect(include_nil = false)
|
8
8
|
keys = include_nil ? key_names : attributes.keys
|
9
9
|
attributes_as_nice_string = keys.sort.collect do |name|
|
10
|
-
"#{name}: #{self
|
10
|
+
"#{name}: #{self.send(:"#{name}").inspect}"
|
11
11
|
end.join(", ")
|
12
12
|
"#<#{self.class} #{attributes_as_nice_string}>"
|
13
13
|
end
|
@@ -10,14 +10,14 @@ module MongoMapper
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def decrement(*args)
|
13
|
-
criteria, keys = criteria_and_keys_from_args(args)
|
13
|
+
criteria, keys, options = criteria_and_keys_from_args(args)
|
14
14
|
values, to_decrement = keys.values, {}
|
15
15
|
keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
|
16
16
|
collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
|
17
17
|
end
|
18
18
|
|
19
19
|
def set(*args)
|
20
|
-
criteria, updates = criteria_and_keys_from_args(args)
|
20
|
+
criteria, updates, options = criteria_and_keys_from_args(args)
|
21
21
|
updates.each do |key, value|
|
22
22
|
updates[key] = keys[key.to_s].set(value) if key?(key)
|
23
23
|
end
|
@@ -64,14 +64,26 @@ module MongoMapper
|
|
64
64
|
|
65
65
|
private
|
66
66
|
def modifier_update(modifier, args)
|
67
|
-
criteria, updates = criteria_and_keys_from_args(args)
|
68
|
-
|
67
|
+
criteria, updates, options = criteria_and_keys_from_args(args)
|
68
|
+
if options
|
69
|
+
collection.update(criteria, {modifier => updates}, options.merge(:multi => true))
|
70
|
+
else
|
71
|
+
collection.update(criteria, {modifier => updates}, :multi => true)
|
72
|
+
end
|
69
73
|
end
|
70
74
|
|
71
75
|
def criteria_and_keys_from_args(args)
|
72
|
-
|
73
|
-
|
74
|
-
|
76
|
+
if args[0].is_a?(Hash)
|
77
|
+
criteria = args[0]
|
78
|
+
updates = args[1]
|
79
|
+
options = args[2]
|
80
|
+
else
|
81
|
+
split_args = args.partition{|a| a.is_a?(BSON::ObjectId)}
|
82
|
+
criteria = {:id => split_args[0]}
|
83
|
+
updates = split_args[1].first
|
84
|
+
options = split_args[1].last
|
85
|
+
end
|
86
|
+
[criteria_hash(criteria).to_hash, updates, options]
|
75
87
|
end
|
76
88
|
end
|
77
89
|
|
@@ -79,41 +91,41 @@ module MongoMapper
|
|
79
91
|
self.class.unset(id, *keys)
|
80
92
|
end
|
81
93
|
|
82
|
-
def increment(hash)
|
83
|
-
self.class.increment(id, hash)
|
94
|
+
def increment(hash, options=nil)
|
95
|
+
self.class.increment(id, hash, options)
|
84
96
|
end
|
85
97
|
|
86
|
-
def decrement(hash)
|
87
|
-
self.class.decrement(id, hash)
|
98
|
+
def decrement(hash, options=nil)
|
99
|
+
self.class.decrement(id, hash, options)
|
88
100
|
end
|
89
101
|
|
90
|
-
def set(hash)
|
91
|
-
self.class.set(id, hash)
|
102
|
+
def set(hash, options=nil)
|
103
|
+
self.class.set(id, hash, options)
|
92
104
|
end
|
93
105
|
|
94
|
-
def push(hash)
|
95
|
-
self.class.push(id, hash)
|
106
|
+
def push(hash, options=nil)
|
107
|
+
self.class.push(id, hash, options)
|
96
108
|
end
|
97
109
|
|
98
|
-
def push_all(hash)
|
99
|
-
self.class.push_all(id, hash)
|
110
|
+
def push_all(hash, options=nil)
|
111
|
+
self.class.push_all(id, hash, options)
|
100
112
|
end
|
101
113
|
|
102
|
-
def pull(hash)
|
103
|
-
self.class.pull(id, hash)
|
114
|
+
def pull(hash, options=nil)
|
115
|
+
self.class.pull(id, hash, options)
|
104
116
|
end
|
105
117
|
|
106
|
-
def pull_all(hash)
|
107
|
-
self.class.pull_all(id, hash)
|
118
|
+
def pull_all(hash, options=nil)
|
119
|
+
self.class.pull_all(id, hash, options)
|
108
120
|
end
|
109
121
|
|
110
|
-
def add_to_set(hash)
|
111
|
-
self.class.push_uniq(id, hash)
|
122
|
+
def add_to_set(hash, options=nil)
|
123
|
+
self.class.push_uniq(id, hash, options)
|
112
124
|
end
|
113
125
|
alias push_uniq add_to_set
|
114
126
|
|
115
|
-
def pop(hash)
|
116
|
-
self.class.pop(id, hash)
|
127
|
+
def pop(hash, options=nil)
|
128
|
+
self.class.pop(id, hash, options)
|
117
129
|
end
|
118
130
|
end
|
119
131
|
end
|
@@ -8,8 +8,11 @@ module MongoMapper
|
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
module ClassMethods
|
11
|
+
extend Forwardable
|
11
12
|
include PluckyMethods
|
12
13
|
|
14
|
+
def_delegators :query, :to_a, :size, :empty?
|
15
|
+
|
13
16
|
def find_each(opts={})
|
14
17
|
super(opts).each { |doc| yield(doc) }
|
15
18
|
end
|
@@ -81,7 +84,7 @@ module MongoMapper
|
|
81
84
|
|
82
85
|
def find_some(ids, options={})
|
83
86
|
query = query(options).amend(:_id => ids.flatten.compact.uniq)
|
84
|
-
|
87
|
+
query.all
|
85
88
|
end
|
86
89
|
|
87
90
|
def find_some!(ids, options={})
|
@@ -95,16 +98,6 @@ module MongoMapper
|
|
95
98
|
docs
|
96
99
|
end
|
97
100
|
|
98
|
-
# All query methods that load documents pass through find_one or find_many
|
99
|
-
def find_one(options={})
|
100
|
-
query(options).first
|
101
|
-
end
|
102
|
-
|
103
|
-
# All query methods that load documents pass through find_one or find_many
|
104
|
-
def find_many(options)
|
105
|
-
query(options).all
|
106
|
-
end
|
107
|
-
|
108
101
|
def initialize_each(*docs)
|
109
102
|
instances = []
|
110
103
|
docs = [{}] if docs.blank?
|
@@ -6,9 +6,15 @@ module MongoMapper
|
|
6
6
|
module Querying
|
7
7
|
module PluckyMethods
|
8
8
|
extend Forwardable
|
9
|
-
def_delegators :query, :where, :
|
10
|
-
:
|
11
|
-
:
|
9
|
+
def_delegators :query, :where, :filter,
|
10
|
+
:fields, :ignore, :only,
|
11
|
+
:limit, :paginate, :per_page, :skip, :offset,
|
12
|
+
:sort, :order, :reverse,
|
13
|
+
:count,
|
14
|
+
:distinct,
|
15
|
+
:last, :first, :find_one, :all, :find_each,
|
16
|
+
:find, :find!,
|
17
|
+
:exists?, :exist?
|
12
18
|
end
|
13
19
|
end
|
14
20
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
module Touch
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def touch(key = :updated_at)
|
7
|
+
raise ArgumentError, "Invalid key named #{key}" unless self.key_names.include?(key.to_s)
|
8
|
+
if self.class.embeddable?
|
9
|
+
self.write_attribute(key, Time.now.utc)
|
10
|
+
self._parent_document.touch
|
11
|
+
else
|
12
|
+
self.set(key => Time.now.utc)
|
13
|
+
end
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/mongo_mapper/version.rb
CHANGED
@@ -393,6 +393,49 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
|
|
393
393
|
|
394
394
|
project.statuses.count(:name => 'Foo').should == 1
|
395
395
|
end
|
396
|
+
|
397
|
+
should "ignore unpersisted documents" do
|
398
|
+
project = Project.create
|
399
|
+
project.statuses.build(:name => 'Foo')
|
400
|
+
project.statuses.count.should == 0
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
context "size" do
|
405
|
+
should "reflect both persisted and new documents" do
|
406
|
+
project = Project.create
|
407
|
+
3.times { project.statuses.create(:name => 'Foo!') }
|
408
|
+
2.times { project.statuses.build(:name => 'Foo!') }
|
409
|
+
project.statuses.size.should == 5
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
context "empty?" do
|
414
|
+
should "be true with no associated docs" do
|
415
|
+
project = Project.create
|
416
|
+
project.statuses.empty?.should be_true
|
417
|
+
end
|
418
|
+
|
419
|
+
should "be false if a document is built" do
|
420
|
+
project = Project.create
|
421
|
+
project.statuses.build(:name => 'Foo!')
|
422
|
+
project.statuses.empty?.should be_false
|
423
|
+
end
|
424
|
+
|
425
|
+
should "be false if a document is created" do
|
426
|
+
project = Project.create
|
427
|
+
project.statuses.create(:name => 'Foo!')
|
428
|
+
project.statuses.empty?.should be_false
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
context "to_a" do
|
433
|
+
should "include persisted and new documents" do
|
434
|
+
project = Project.create
|
435
|
+
3.times { project.statuses.create(:name => 'Foo!') }
|
436
|
+
2.times { project.statuses.build(:name => 'Foo!') }
|
437
|
+
project.statuses.to_a.size.should == 5
|
438
|
+
end
|
396
439
|
end
|
397
440
|
|
398
441
|
context "to_json" do
|
@@ -801,4 +844,23 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
|
|
801
844
|
article.paper_id.should == @paper.id
|
802
845
|
end
|
803
846
|
end
|
847
|
+
|
848
|
+
context "criteria" do
|
849
|
+
setup do
|
850
|
+
News::Paper.many :articles, :class_name => 'News::Article'
|
851
|
+
News::Article.belongs_to :paper, :class_name => 'News::Paper'
|
852
|
+
|
853
|
+
@paper = News::Paper.create
|
854
|
+
end
|
855
|
+
|
856
|
+
should "should find associated instances by an object ID" do
|
857
|
+
article = News::Article.create(:paper_id => @paper.id)
|
858
|
+
@paper.articles.should include(article)
|
859
|
+
end
|
860
|
+
|
861
|
+
should "should find associated instances by a string" do
|
862
|
+
article = News::Article.create(:paper_id => @paper.id.to_s)
|
863
|
+
@paper.articles.should include(article)
|
864
|
+
end
|
865
|
+
end
|
804
866
|
end
|
@@ -31,298 +31,323 @@ class ModifierTest < Test::Unit::TestCase
|
|
31
31
|
@page = @page_class.create(:title => 'Home', :tags => %w(foo bar))
|
32
32
|
@page2 = @page_class.create(:title => 'Home')
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
should "work with criteria and keys" do
|
36
36
|
@page_class.unset({:title => 'Home'}, :title, :tags)
|
37
37
|
assert_keys_removed @page, :title, :tags
|
38
38
|
assert_keys_removed @page2, :title, :tags
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
should "work with ids and keys" do
|
42
42
|
@page_class.unset(@page.id, @page2.id, :title, :tags)
|
43
43
|
assert_keys_removed @page, :title, :tags
|
44
44
|
assert_keys_removed @page2, :title, :tags
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
context "increment" do
|
49
49
|
setup do
|
50
50
|
@page = @page_class.create(:title => 'Home')
|
51
51
|
@page2 = @page_class.create(:title => 'Home')
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
should "work with criteria and modifier hashes" do
|
55
55
|
@page_class.increment({:title => 'Home'}, :day_count => 1, :week_count => 2, :month_count => 3)
|
56
|
-
|
56
|
+
|
57
57
|
assert_page_counts @page, 1, 2, 3
|
58
58
|
assert_page_counts @page2, 1, 2, 3
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
should "work with ids and modifier hash" do
|
62
62
|
@page_class.increment(@page.id, @page2.id, :day_count => 1, :week_count => 2, :month_count => 3)
|
63
|
-
|
63
|
+
|
64
64
|
assert_page_counts @page, 1, 2, 3
|
65
65
|
assert_page_counts @page2, 1, 2, 3
|
66
66
|
end
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
context "decrement" do
|
70
70
|
setup do
|
71
71
|
@page = @page_class.create(:title => 'Home', :day_count => 1, :week_count => 2, :month_count => 3)
|
72
72
|
@page2 = @page_class.create(:title => 'Home', :day_count => 1, :week_count => 2, :month_count => 3)
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
should "work with criteria and modifier hashes" do
|
76
76
|
@page_class.decrement({:title => 'Home'}, :day_count => 1, :week_count => 2, :month_count => 3)
|
77
|
-
|
77
|
+
|
78
78
|
assert_page_counts @page, 0, 0, 0
|
79
79
|
assert_page_counts @page2, 0, 0, 0
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
should "work with ids and modifier hash" do
|
83
83
|
@page_class.decrement(@page.id, @page2.id, :day_count => 1, :week_count => 2, :month_count => 3)
|
84
|
-
|
84
|
+
|
85
85
|
assert_page_counts @page, 0, 0, 0
|
86
86
|
assert_page_counts @page2, 0, 0, 0
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
should "decrement with positive or negative numbers" do
|
90
90
|
@page_class.decrement(@page.id, @page2.id, :day_count => -1, :week_count => 2, :month_count => -3)
|
91
|
-
|
91
|
+
|
92
92
|
assert_page_counts @page, 0, 0, 0
|
93
93
|
assert_page_counts @page2, 0, 0, 0
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
context "set" do
|
98
98
|
setup do
|
99
99
|
@page = @page_class.create(:title => 'Home')
|
100
100
|
@page2 = @page_class.create(:title => 'Home')
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
should "work with criteria and modifier hashes" do
|
104
104
|
@page_class.set({:title => 'Home'}, :title => 'Home Revised')
|
105
|
-
|
105
|
+
|
106
106
|
@page.reload
|
107
107
|
@page.title.should == 'Home Revised'
|
108
|
-
|
108
|
+
|
109
109
|
@page2.reload
|
110
110
|
@page2.title.should == 'Home Revised'
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
should "work with ids and modifier hash" do
|
114
114
|
@page_class.set(@page.id, @page2.id, :title => 'Home Revised')
|
115
|
-
|
115
|
+
|
116
116
|
@page.reload
|
117
117
|
@page.title.should == 'Home Revised'
|
118
|
-
|
118
|
+
|
119
119
|
@page2.reload
|
120
120
|
@page2.title.should == 'Home Revised'
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
should "typecast values before querying" do
|
124
124
|
@page_class.key :tags, Set
|
125
|
-
|
125
|
+
|
126
126
|
assert_nothing_raised do
|
127
127
|
@page_class.set(@page.id, :tags => ['foo', 'bar'].to_set)
|
128
128
|
@page.reload
|
129
129
|
@page.tags.should == Set.new(['foo', 'bar'])
|
130
130
|
end
|
131
131
|
end
|
132
|
-
|
132
|
+
|
133
133
|
should "not typecast keys that are not defined in document" do
|
134
134
|
assert_raises(BSON::InvalidDocument) do
|
135
135
|
@page_class.set(@page.id, :colors => ['red', 'green'].to_set)
|
136
136
|
end
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
should "set keys that are not defined in document" do
|
140
140
|
@page_class.set(@page.id, :colors => %w[red green])
|
141
141
|
@page.reload
|
142
142
|
@page[:colors].should == %w[red green]
|
143
143
|
end
|
144
144
|
end
|
145
|
-
|
145
|
+
|
146
146
|
context "push" do
|
147
147
|
setup do
|
148
148
|
@page = @page_class.create(:title => 'Home')
|
149
149
|
@page2 = @page_class.create(:title => 'Home')
|
150
150
|
end
|
151
|
-
|
151
|
+
|
152
152
|
should "work with criteria and modifier hashes" do
|
153
153
|
@page_class.push({:title => 'Home'}, :tags => 'foo')
|
154
|
-
|
154
|
+
|
155
155
|
@page.reload
|
156
156
|
@page.tags.should == %w(foo)
|
157
|
-
|
157
|
+
|
158
158
|
@page2.reload
|
159
159
|
@page2.tags.should == %w(foo)
|
160
160
|
end
|
161
|
-
|
161
|
+
|
162
162
|
should "work with ids and modifier hash" do
|
163
163
|
@page_class.push(@page.id, @page2.id, :tags => 'foo')
|
164
|
-
|
164
|
+
|
165
165
|
@page.reload
|
166
166
|
@page.tags.should == %w(foo)
|
167
|
-
|
167
|
+
|
168
168
|
@page2.reload
|
169
169
|
@page2.tags.should == %w(foo)
|
170
170
|
end
|
171
171
|
end
|
172
|
-
|
172
|
+
|
173
173
|
context "push_all" do
|
174
174
|
setup do
|
175
175
|
@page = @page_class.create(:title => 'Home')
|
176
176
|
@page2 = @page_class.create(:title => 'Home')
|
177
177
|
@tags = %w(foo bar)
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
should "work with criteria and modifier hashes" do
|
181
181
|
@page_class.push_all({:title => 'Home'}, :tags => @tags)
|
182
|
-
|
182
|
+
|
183
183
|
@page.reload
|
184
184
|
@page.tags.should == @tags
|
185
|
-
|
185
|
+
|
186
186
|
@page2.reload
|
187
187
|
@page2.tags.should == @tags
|
188
188
|
end
|
189
|
-
|
189
|
+
|
190
190
|
should "work with ids and modifier hash" do
|
191
191
|
@page_class.push_all(@page.id, @page2.id, :tags => @tags)
|
192
|
-
|
192
|
+
|
193
193
|
@page.reload
|
194
194
|
@page.tags.should == @tags
|
195
|
-
|
195
|
+
|
196
196
|
@page2.reload
|
197
197
|
@page2.tags.should == @tags
|
198
198
|
end
|
199
199
|
end
|
200
|
-
|
200
|
+
|
201
201
|
context "pull" do
|
202
202
|
setup do
|
203
203
|
@page = @page_class.create(:title => 'Home', :tags => %w(foo bar))
|
204
204
|
@page2 = @page_class.create(:title => 'Home', :tags => %w(foo bar))
|
205
205
|
end
|
206
|
-
|
206
|
+
|
207
207
|
should "work with criteria and modifier hashes" do
|
208
208
|
@page_class.pull({:title => 'Home'}, :tags => 'foo')
|
209
|
-
|
209
|
+
|
210
210
|
@page.reload
|
211
211
|
@page.tags.should == %w(bar)
|
212
|
-
|
212
|
+
|
213
213
|
@page2.reload
|
214
214
|
@page2.tags.should == %w(bar)
|
215
215
|
end
|
216
|
-
|
216
|
+
|
217
217
|
should "be able to pull with ids and modifier hash" do
|
218
218
|
@page_class.pull(@page.id, @page2.id, :tags => 'foo')
|
219
|
-
|
219
|
+
|
220
220
|
@page.reload
|
221
221
|
@page.tags.should == %w(bar)
|
222
|
-
|
222
|
+
|
223
223
|
@page2.reload
|
224
224
|
@page2.tags.should == %w(bar)
|
225
225
|
end
|
226
226
|
end
|
227
|
-
|
227
|
+
|
228
228
|
context "pull_all" do
|
229
229
|
setup do
|
230
230
|
@page = @page_class.create(:title => 'Home', :tags => %w(foo bar baz))
|
231
231
|
@page2 = @page_class.create(:title => 'Home', :tags => %w(foo bar baz))
|
232
232
|
end
|
233
|
-
|
233
|
+
|
234
234
|
should "work with criteria and modifier hashes" do
|
235
235
|
@page_class.pull_all({:title => 'Home'}, :tags => %w(foo bar))
|
236
|
-
|
236
|
+
|
237
237
|
@page.reload
|
238
238
|
@page.tags.should == %w(baz)
|
239
|
-
|
239
|
+
|
240
240
|
@page2.reload
|
241
241
|
@page2.tags.should == %w(baz)
|
242
242
|
end
|
243
|
-
|
243
|
+
|
244
244
|
should "work with ids and modifier hash" do
|
245
245
|
@page_class.pull_all(@page.id, @page2.id, :tags => %w(foo bar))
|
246
|
-
|
246
|
+
|
247
247
|
@page.reload
|
248
248
|
@page.tags.should == %w(baz)
|
249
|
-
|
249
|
+
|
250
250
|
@page2.reload
|
251
251
|
@page2.tags.should == %w(baz)
|
252
252
|
end
|
253
253
|
end
|
254
|
-
|
254
|
+
|
255
255
|
context "add_to_set" do
|
256
256
|
setup do
|
257
257
|
@page = @page_class.create(:title => 'Home', :tags => 'foo')
|
258
258
|
@page2 = @page_class.create(:title => 'Home')
|
259
259
|
end
|
260
|
-
|
260
|
+
|
261
261
|
should "be able to add to set with criteria and modifier hash" do
|
262
262
|
@page_class.add_to_set({:title => 'Home'}, :tags => 'foo')
|
263
|
-
|
263
|
+
|
264
264
|
@page.reload
|
265
265
|
@page.tags.should == %w(foo)
|
266
|
-
|
266
|
+
|
267
267
|
@page2.reload
|
268
268
|
@page2.tags.should == %w(foo)
|
269
269
|
end
|
270
|
-
|
270
|
+
|
271
271
|
should "be able to add to set with ids and modifier hash" do
|
272
272
|
@page_class.add_to_set(@page.id, @page2.id, :tags => 'foo')
|
273
|
-
|
273
|
+
|
274
274
|
@page.reload
|
275
275
|
@page.tags.should == %w(foo)
|
276
|
-
|
276
|
+
|
277
277
|
@page2.reload
|
278
278
|
@page2.tags.should == %w(foo)
|
279
279
|
end
|
280
280
|
end
|
281
|
-
|
281
|
+
|
282
282
|
context "push_uniq" do
|
283
283
|
setup do
|
284
284
|
@page = @page_class.create(:title => 'Home', :tags => 'foo')
|
285
285
|
@page2 = @page_class.create(:title => 'Home')
|
286
286
|
end
|
287
|
-
|
287
|
+
|
288
288
|
should "be able to push uniq with criteria and modifier hash" do
|
289
289
|
@page_class.push_uniq({:title => 'Home'}, :tags => 'foo')
|
290
|
-
|
290
|
+
|
291
291
|
@page.reload
|
292
292
|
@page.tags.should == %w(foo)
|
293
|
-
|
293
|
+
|
294
294
|
@page2.reload
|
295
295
|
@page2.tags.should == %w(foo)
|
296
296
|
end
|
297
|
-
|
297
|
+
|
298
298
|
should "be able to push uniq with ids and modifier hash" do
|
299
299
|
@page_class.push_uniq(@page.id, @page2.id, :tags => 'foo')
|
300
|
-
|
300
|
+
|
301
301
|
@page.reload
|
302
302
|
@page.tags.should == %w(foo)
|
303
|
-
|
303
|
+
|
304
304
|
@page2.reload
|
305
305
|
@page2.tags.should == %w(foo)
|
306
306
|
end
|
307
307
|
end
|
308
|
-
|
308
|
+
|
309
309
|
context "pop" do
|
310
310
|
setup do
|
311
311
|
@page = @page_class.create(:title => 'Home', :tags => %w(foo bar))
|
312
312
|
end
|
313
|
-
|
313
|
+
|
314
314
|
should "be able to remove the last element the array" do
|
315
315
|
@page_class.pop(@page.id, :tags => 1)
|
316
316
|
@page.reload
|
317
317
|
@page.tags.should == %w(foo)
|
318
318
|
end
|
319
|
-
|
319
|
+
|
320
320
|
should "be able to remove the first element of the array" do
|
321
321
|
@page_class.pop(@page.id, :tags => -1)
|
322
322
|
@page.reload
|
323
323
|
@page.tags.should == %w(bar)
|
324
324
|
end
|
325
325
|
end
|
326
|
+
|
327
|
+
context "additional options (upsert & safe)" do
|
328
|
+
should "be able to pass upsert option" do
|
329
|
+
new_key_value = DateTime.now.to_s
|
330
|
+
@page_class.increment({:title => new_key_value}, {:day_count => 1}, {:upsert => true})
|
331
|
+
@page_class.count(:title => new_key_value).should == 1
|
332
|
+
@page_class.first(:title => new_key_value).day_count.should == 1
|
333
|
+
end
|
334
|
+
|
335
|
+
should "be able to pass safe option" do
|
336
|
+
@page_class.create(:title => "Better Be Safe than Sorry")
|
337
|
+
|
338
|
+
# We are trying to increment a key of type string here which should fail
|
339
|
+
assert_raises(Mongo::OperationFailure) do
|
340
|
+
@page_class.increment({:title => "Better Be Safe than Sorry"}, {:title => 1}, {:safe => true})
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
should "be able to pass both safe and upsert options" do
|
345
|
+
new_key_value = DateTime.now.to_s
|
346
|
+
@page_class.increment({:title => new_key_value}, {:day_count => 1}, {:upsert => true, :safe => true})
|
347
|
+
@page_class.count(:title => new_key_value).should == 1
|
348
|
+
@page_class.first(:title => new_key_value).day_count.should == 1
|
349
|
+
end
|
350
|
+
end
|
326
351
|
end
|
327
352
|
|
328
353
|
context "instance methods" do
|
@@ -331,102 +356,128 @@ class ModifierTest < Test::Unit::TestCase
|
|
331
356
|
page.unset(:title, :tags)
|
332
357
|
assert_keys_removed page, :title, :tags
|
333
358
|
end
|
334
|
-
|
359
|
+
|
335
360
|
should "be able to increment with modifier hashes" do
|
336
361
|
page = @page_class.create
|
337
362
|
page.increment(:day_count => 1, :week_count => 2, :month_count => 3)
|
338
|
-
|
363
|
+
|
339
364
|
assert_page_counts page, 1, 2, 3
|
340
365
|
end
|
341
|
-
|
366
|
+
|
342
367
|
should "be able to decrement with modifier hashes" do
|
343
368
|
page = @page_class.create(:day_count => 1, :week_count => 2, :month_count => 3)
|
344
369
|
page.decrement(:day_count => 1, :week_count => 2, :month_count => 3)
|
345
|
-
|
370
|
+
|
346
371
|
assert_page_counts page, 0, 0, 0
|
347
372
|
end
|
348
|
-
|
373
|
+
|
349
374
|
should "always decrement when decrement is called whether number is positive or negative" do
|
350
375
|
page = @page_class.create(:day_count => 1, :week_count => 2, :month_count => 3)
|
351
376
|
page.decrement(:day_count => -1, :week_count => 2, :month_count => -3)
|
352
|
-
|
377
|
+
|
353
378
|
assert_page_counts page, 0, 0, 0
|
354
379
|
end
|
355
|
-
|
380
|
+
|
356
381
|
should "be able to set with modifier hashes" do
|
357
382
|
page = @page_class.create(:title => 'Home')
|
358
383
|
page.set(:title => 'Home Revised')
|
359
|
-
|
384
|
+
|
360
385
|
page.reload
|
361
386
|
page.title.should == 'Home Revised'
|
362
387
|
end
|
363
|
-
|
388
|
+
|
364
389
|
should "be able to push with modifier hashes" do
|
365
390
|
page = @page_class.create
|
366
391
|
page.push(:tags => 'foo')
|
367
|
-
|
392
|
+
|
368
393
|
page.reload
|
369
394
|
page.tags.should == %w(foo)
|
370
395
|
end
|
371
|
-
|
396
|
+
|
372
397
|
should "be able to push_all with modifier hashes" do
|
373
398
|
page = @page_class.create
|
374
399
|
page.push_all(:tags => %w(foo bar))
|
375
|
-
|
400
|
+
|
376
401
|
page.reload
|
377
402
|
page.tags.should == %w(foo bar)
|
378
403
|
end
|
379
|
-
|
404
|
+
|
380
405
|
should "be able to pull with criteria and modifier hashes" do
|
381
406
|
page = @page_class.create(:tags => %w(foo bar))
|
382
407
|
page.pull(:tags => 'foo')
|
383
|
-
|
408
|
+
|
384
409
|
page.reload
|
385
410
|
page.tags.should == %w(bar)
|
386
411
|
end
|
387
|
-
|
412
|
+
|
388
413
|
should "be able to pull_all with criteria and modifier hashes" do
|
389
414
|
page = @page_class.create(:tags => %w(foo bar baz))
|
390
415
|
page.pull_all(:tags => %w(foo bar))
|
391
|
-
|
416
|
+
|
392
417
|
page.reload
|
393
418
|
page.tags.should == %w(baz)
|
394
419
|
end
|
395
|
-
|
420
|
+
|
396
421
|
should "be able to add_to_set with criteria and modifier hash" do
|
397
422
|
page = @page_class.create(:tags => 'foo')
|
398
423
|
page2 = @page_class.create
|
399
|
-
|
424
|
+
|
400
425
|
page.add_to_set(:tags => 'foo')
|
401
426
|
page2.add_to_set(:tags => 'foo')
|
402
|
-
|
427
|
+
|
403
428
|
page.reload
|
404
429
|
page.tags.should == %w(foo)
|
405
|
-
|
430
|
+
|
406
431
|
page2.reload
|
407
432
|
page2.tags.should == %w(foo)
|
408
433
|
end
|
409
|
-
|
434
|
+
|
410
435
|
should "be able to push uniq with criteria and modifier hash" do
|
411
436
|
page = @page_class.create(:tags => 'foo')
|
412
437
|
page2 = @page_class.create
|
413
|
-
|
438
|
+
|
414
439
|
page.push_uniq(:tags => 'foo')
|
415
440
|
page2.push_uniq(:tags => 'foo')
|
416
|
-
|
441
|
+
|
417
442
|
page.reload
|
418
443
|
page.tags.should == %w(foo)
|
419
|
-
|
444
|
+
|
420
445
|
page2.reload
|
421
446
|
page2.tags.should == %w(foo)
|
422
447
|
end
|
423
|
-
|
448
|
+
|
424
449
|
should "be able to pop with modifier hashes" do
|
425
450
|
page = @page_class.create(:tags => %w(foo bar))
|
426
451
|
page.pop(:tags => 1)
|
427
|
-
|
452
|
+
|
428
453
|
page.reload
|
429
454
|
page.tags.should == %w(foo)
|
430
455
|
end
|
456
|
+
|
457
|
+
should "be able to pass upsert option" do
|
458
|
+
page = @page_class.create(:title => "Upsert Page")
|
459
|
+
page.increment({:new_count => 1}, {:upsert => true})
|
460
|
+
|
461
|
+
page.reload
|
462
|
+
page.new_count.should == 1
|
463
|
+
end
|
464
|
+
|
465
|
+
should "be able to pass safe option" do
|
466
|
+
page = @page_class.create(:title => "Safe Page")
|
467
|
+
|
468
|
+
# We are trying to increment a key of type string here which should fail
|
469
|
+
assert_raises(Mongo::OperationFailure) do
|
470
|
+
page.increment({:title => 1}, {:safe => true})
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
should "be able to pass upsert and safe options" do
|
475
|
+
page = @page_class.create(:title => "Upsert and Safe Page")
|
476
|
+
page.increment({:another_count => 1}, {:upsert => true, :safe => true})
|
477
|
+
|
478
|
+
page.reload
|
479
|
+
page.another_count.should == 1
|
480
|
+
end
|
481
|
+
|
431
482
|
end
|
432
483
|
end
|