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.
@@ -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
@@ -22,6 +22,7 @@ module MongoMapper
22
22
  include Plugins::Timestamps
23
23
  include Plugins::Validations
24
24
  include Plugins::EmbeddedCallbacks
25
+ include Plugins::Touch
25
26
 
26
27
  included do
27
28
  extend Plugins
@@ -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
- # strip milliseconds as Ruby does micro and bson does milli and rounding rounded wrong
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
@@ -4,6 +4,7 @@ module MongoMapper
4
4
  module Associations
5
5
  class SingleAssociation < Base
6
6
  def setup(model)
7
+ @model = model
7
8
  model.associations_module.module_eval <<-end_eval
8
9
  def #{name}
9
10
  proxy = get_proxy(associations[#{name.inspect}])
@@ -7,6 +7,10 @@ module MongoMapper
7
7
  def destroy
8
8
  run_callbacks(:destroy) { super }
9
9
  end
10
+
11
+ def touch(*)
12
+ run_callbacks(:touch) { super }
13
+ end
10
14
 
11
15
  private
12
16
  def create_or_update(*)
@@ -8,6 +8,7 @@ module MongoMapper
8
8
  extend ::ActiveModel::Callbacks
9
9
 
10
10
  define_model_callbacks :save, :create, :update, :destroy, :only => [:before, :after]
11
+ define_model_callbacks :touch, :only => [:after]
11
12
  end
12
13
 
13
14
  def run_callbacks(callback, *args, &block)
@@ -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[name].inspect}"
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
- collection.update(criteria, {modifier => updates}, :multi => true)
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
- keys = args.pop
73
- criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
74
- [criteria_hash(criteria).to_hash, keys]
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
- find_many(query.to_hash).compact
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, :fields, :limit, :skip, :sort,
10
- :count, :last, :first, :all, :paginate,
11
- :find, :find!, :exists?, :exist?, :find_each
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
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module MongoMapper
3
- Version = '0.11.0'
3
+ Version = '0.11.1'
4
4
  end
@@ -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