mongo_mapper 0.13.0 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mongo_mapper.rb +3 -0
  3. data/lib/mongo_mapper/connection.rb +4 -3
  4. data/lib/mongo_mapper/document.rb +2 -0
  5. data/lib/mongo_mapper/extensions/symbol.rb +18 -0
  6. data/lib/mongo_mapper/plugins/accessible.rb +10 -1
  7. data/lib/mongo_mapper/plugins/associations/base.rb +5 -1
  8. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +9 -0
  9. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +0 -0
  10. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +0 -0
  11. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +0 -0
  12. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +0 -0
  13. data/lib/mongo_mapper/plugins/associations/proxy.rb +2 -2
  14. data/lib/mongo_mapper/plugins/counter_cache.rb +78 -0
  15. data/lib/mongo_mapper/plugins/indexes.rb +0 -0
  16. data/lib/mongo_mapper/plugins/keys.rb +14 -2
  17. data/lib/mongo_mapper/plugins/modifiers.rb +0 -0
  18. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +0 -0
  19. data/lib/mongo_mapper/plugins/rails.rb +1 -0
  20. data/lib/mongo_mapper/plugins/sci.rb +0 -0
  21. data/lib/mongo_mapper/plugins/stats.rb +19 -0
  22. data/lib/mongo_mapper/plugins/validations.rb +1 -1
  23. data/lib/mongo_mapper/railtie.rb +3 -3
  24. data/lib/mongo_mapper/version.rb +1 -1
  25. data/spec/functional/counter_cache_spec.rb +146 -0
  26. data/spec/functional/document_spec.rb +28 -0
  27. data/spec/functional/indexes_spec.rb +0 -0
  28. data/spec/functional/keys_spec.rb +31 -0
  29. data/spec/functional/sci_spec.rb +0 -0
  30. data/spec/functional/stats_spec.rb +74 -0
  31. data/spec/quality_spec.rb +51 -0
  32. data/spec/unit/associations/proxy_spec.rb +5 -0
  33. data/spec/unit/extensions_spec.rb +24 -0
  34. data/spec/unit/key_spec.rb +0 -0
  35. data/spec/unit/model_generator_spec.rb +0 -0
  36. data/spec/unit/rails_spec.rb +5 -0
  37. metadata +28 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cd7ff4dfcd2b6bce162c7b55ba45e8c00e38a461
4
- data.tar.gz: 673686bd40a1c139e2045b5397802239cd5d894c
3
+ metadata.gz: 3e78985587a63e18283384630db3c316ee260b20
4
+ data.tar.gz: 5f2d55cbe5df4c2f8322088cb9f0edfaa84a69e9
5
5
  SHA512:
6
- metadata.gz: 36943d83bc3ddff1cd8c82d8bddfdde2fa3dfae12800f4c93260480185925e1f34e5a8622b7682b176a318579ee723339286a5c5b99678e9731301e475fb183b
7
- data.tar.gz: 039605ede2145f91ef107e39dc91d43db57906be355737198fe0a1cff97a2eeb821a9a9460fa977f1a2cc520cdf07c1177994db5ad623e298203e50e6f5838a4
6
+ metadata.gz: cf19d01f18a16676486f87db3e0db2c6894c6542f8492ed63b72cd9dbb24ae4dd90f26c5ec226a98fdc1636539a5a9a410c813bffba5923fa95a06fcc873bc4b
7
+ data.tar.gz: 0b915ec964c1bafa1c3432061d91800029f291ce7799945830129d5c4109b1c2c21902ed8eb31ebb6c5648cb46c4775fe692d46614078ba001dabc95606ca3d0
data/lib/mongo_mapper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  require 'plucky'
3
+ require 'active_support'
3
4
  require 'active_support/core_ext'
4
5
  require 'active_model'
5
6
  require "mongo_mapper/railtie" if defined?(Rails)
@@ -35,6 +36,7 @@ module MongoMapper
35
36
  autoload :Callbacks, 'mongo_mapper/plugins/callbacks'
36
37
  autoload :Caching, 'mongo_mapper/plugins/caching'
37
38
  autoload :Clone, 'mongo_mapper/plugins/clone'
39
+ autoload :CounterCache, 'mongo_mapper/plugins/counter_cache'
38
40
  autoload :Dirty, 'mongo_mapper/plugins/dirty'
39
41
  autoload :Document, 'mongo_mapper/plugins/document'
40
42
  autoload :DynamicQuerying, 'mongo_mapper/plugins/dynamic_querying'
@@ -57,6 +59,7 @@ module MongoMapper
57
59
  autoload :Sci, 'mongo_mapper/plugins/sci'
58
60
  autoload :Scopes, 'mongo_mapper/plugins/scopes'
59
61
  autoload :Serialization, 'mongo_mapper/plugins/serialization'
62
+ autoload :Stats, 'mongo_mapper/plugins/stats'
60
63
  autoload :Timestamps, 'mongo_mapper/plugins/timestamps'
61
64
  autoload :Userstamps, 'mongo_mapper/plugins/userstamps'
62
65
  autoload :Validations, 'mongo_mapper/plugins/validations'
@@ -78,11 +78,12 @@ module MongoMapper
78
78
  options[:ssl] = env['ssl']
79
79
  end
80
80
 
81
- MongoMapper.connection = if env['hosts']
81
+ MongoMapper.connection = if env.key?('hosts')
82
+ klass = (env.key?("mongos") || env.key?("sharded")) ? Mongo::MongoShardedClient : Mongo::MongoReplicaSetClient
82
83
  if env['hosts'].first.is_a?(String)
83
- Mongo::MongoReplicaSetClient.new( env['hosts'], options )
84
+ klass.new( env['hosts'], options )
84
85
  else
85
- Mongo::MongoReplicaSetClient.new( *env['hosts'].push(options) )
86
+ klass.new( *env['hosts'].push(options) )
86
87
  end
87
88
  else
88
89
  Mongo::MongoClient.new(env['host'], env['port'], options)
@@ -28,6 +28,7 @@ module MongoMapper
28
28
  include Plugins::Sci
29
29
  include Plugins::Scopes
30
30
  include Plugins::Serialization
31
+ include Plugins::Stats
31
32
  include Plugins::Timestamps
32
33
  include Plugins::Userstamps
33
34
  include Plugins::Touch
@@ -35,6 +36,7 @@ module MongoMapper
35
36
  include Plugins::EmbeddedCallbacks
36
37
  include Plugins::Callbacks # for now callbacks needs to be after validations
37
38
  include Plugins::IdentityMap
39
+ include Plugins::CounterCache
38
40
 
39
41
  included do
40
42
  extend Plugins
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Symbol
5
+ def to_mongo(value)
6
+ value && value.to_s.to_sym
7
+ end
8
+
9
+ def from_mongo(value)
10
+ value && value.to_s.to_sym
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class Symbol
17
+ extend MongoMapper::Extensions::Symbol
18
+ end
@@ -45,7 +45,16 @@ module MongoMapper
45
45
  protected
46
46
  def filter_inaccessible_attrs(attrs)
47
47
  return attrs if !accessible_attributes? || attrs.blank?
48
- attrs.dup.delete_if { |key, val| !accessible_attributes.include?(key.to_sym) }
48
+ attrs.dup.delete_if { |key, val| attribute_inaccessible?(key.to_sym) }
49
+ end
50
+
51
+ def attribute_inaccessible?(attribute)
52
+ unless accessible_attributes.include?(attribute)
53
+ message = "Can't mass-assign protected attribute: #{attribute}"
54
+ MongoMapper.logger ? MongoMapper.logger.warn(message) : puts(message)
55
+
56
+ return true
57
+ end
49
58
  end
50
59
  end
51
60
  end
@@ -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, :touch]
9
+ AssociationOptions = [:as, :class, :class_name, :dependent, :extend, :foreign_key, :in, :polymorphic, :autosave, :touch, :counter_cache]
10
10
 
11
11
  def initialize(name, options={}, &extension)
12
12
  @name, @options, @query_options, @original_options = name.to_sym, {}, {}, options
@@ -43,6 +43,10 @@ module MongoMapper
43
43
  !!@options[:touch]
44
44
  end
45
45
 
46
+ def counter_cache?
47
+ !!@options[:counter_cache]
48
+ end
49
+
46
50
  def type_key_name
47
51
  "_type"
48
52
  end
@@ -20,6 +20,7 @@ module MongoMapper
20
20
  model.key type_key_name, String unless model.key?(type_key_name) if polymorphic?
21
21
  super
22
22
  add_touch_callbacks if touch?
23
+ add_counter_cache if counter_cache?
23
24
  end
24
25
 
25
26
  def autosave?
@@ -46,7 +47,15 @@ module MongoMapper
46
47
  @model.after_save(method_name)
47
48
  @model.after_touch(method_name)
48
49
  @model.after_destroy(method_name)
50
+ end
51
+
52
+ def add_counter_cache
53
+ options = {}
54
+ if @options[:counter_cache] && @options[:counter_cache] != true
55
+ options[:field] = @options[:counter_cache]
56
+ end
49
57
 
58
+ @model.counter_cache name, options
50
59
  end
51
60
  end
52
61
  end
@@ -91,12 +91,12 @@ module MongoMapper
91
91
  proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
92
92
  end
93
93
 
94
- def send(method, *args)
94
+ def send(method, *args, &block)
95
95
  if proxy_respond_to?(method, true)
96
96
  super
97
97
  else
98
98
  load_target
99
- target.send(method, *args)
99
+ target.send(method, *args, &block)
100
100
  end
101
101
  end
102
102
 
@@ -0,0 +1,78 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ # Counter Caching for MongoMapper::Document
4
+ #
5
+ # Examples:
6
+ #
7
+ # class Post
8
+ # belongs_to :user
9
+ # counter_cache :user
10
+ # end
11
+ #
12
+ # or:
13
+ #
14
+ # class Post
15
+ # belongs_to :user
16
+ # counter_cache :user, :custom_posts_count
17
+ # end
18
+ #
19
+ # Field names follow rails conventions, so counter_cache :user will increment the Integer field `posts_count' on User
20
+ #
21
+ # Alternatively, you can also use the more common ActiveRecord syntax:
22
+ #
23
+ # class Post
24
+ # belongs_to :user, :counter_cache => true
25
+ # end
26
+ #
27
+ # Or with an alternative field name:
28
+ #
29
+ # class Post
30
+ # belongs_to :user, :counter_cache => :custom_posts_count
31
+ # end
32
+ #
33
+ module CounterCache
34
+ class InvalidCounterCacheError < StandardError; end
35
+
36
+ extend ActiveSupport::Concern
37
+
38
+ module ClassMethods
39
+ def counter_cache(association_name, options = {})
40
+ options.symbolize_keys!
41
+
42
+ field = options[:field] ?
43
+ options[:field] :
44
+ "#{self.collection_name.gsub(/.*\./, '')}_count"
45
+
46
+ association = associations[association_name]
47
+
48
+ if !association
49
+ raise InvalidCounterCacheError, "You must define an association with name `#{association_name}' on model #{self}"
50
+ end
51
+
52
+ association_class = association.klass
53
+ key_names = association_class.keys.keys
54
+
55
+ if !key_names.include?(field.to_s)
56
+ raise InvalidCounterCacheError, "Missing `key #{field.to_sym.inspect}, Integer, :default => 0' on model #{association_class}"
57
+ end
58
+
59
+ after_create do
60
+ if obj = self.send(association_name)
61
+ obj.increment(field => 1)
62
+ obj.write_attribute(field, obj.read_attribute(field) + 1)
63
+ end
64
+ true
65
+ end
66
+
67
+ after_destroy do
68
+ if obj = self.send(association_name)
69
+ obj.decrement(field => 1)
70
+ obj.write_attribute(field, obj.read_attribute(field) - 1)
71
+ end
72
+ true
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
File without changes
@@ -246,8 +246,20 @@ module MongoMapper
246
246
  a_name = [name]
247
247
 
248
248
  _validators.reject!{ |key, _| key == name }
249
- _validate_callbacks.reject! {|callback| callback.raw_filter.attributes == a_name }
249
+ remove_validate_callbacks a_name
250
250
  end
251
+
252
+ def remove_validate_callbacks(a_name)
253
+ chain = _validate_callbacks.dup.reject do |callback|
254
+ f = callback.raw_filter
255
+ f.respond_to?(:attributes) && f.attributes == a_name
256
+ end
257
+ reset_callbacks(:validate)
258
+ chain.each do |callback|
259
+ set_callback 'validate', callback.raw_filter
260
+ end
261
+ end
262
+
251
263
  end
252
264
 
253
265
  def initialize(attrs={})
@@ -293,7 +305,7 @@ module MongoMapper
293
305
 
294
306
  embedded_associations.each do |association|
295
307
  if documents = instance_variable_get(association.ivar)
296
- if association.instance_of?(Associations::OneAssociation)
308
+ if association.is_a?(Associations::OneAssociation)
297
309
  attrs[association.name] = documents.to_mongo
298
310
  else
299
311
  attrs[association.name] = documents.map(&:to_mongo)
File without changes
@@ -36,6 +36,7 @@ module MongoMapper
36
36
 
37
37
  def write_attribute(name, value)
38
38
  self[name] = value
39
+ self[name]
39
40
  end
40
41
 
41
42
  def write_key(name, value)
File without changes
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ module MongoMapper
4
+ module Plugins
5
+ module Stats
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def stats
10
+ stats = collection.stats
11
+
12
+ Struct.new(*stats.keys.collect { |key| key.underscore.to_sym }).new(*stats.values)
13
+ rescue
14
+ nil
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -34,7 +34,7 @@ module MongoMapper
34
34
  end
35
35
 
36
36
  if ::ActiveModel::VERSION::MAJOR < 4 ||
37
- (::ActiveModel::VERSION::MAJOR == 4 && ::ActiveModel::VERSION::MINOR == 0)
37
+ (::ActiveModel::VERSION::MAJOR == 4 && ::ActiveModel::VERSION::MINOR == 0)
38
38
 
39
39
  def setup(klass)
40
40
  @klass = klass
@@ -14,9 +14,9 @@ module MongoMapper
14
14
  # Rescue responses similar to ActiveRecord.
15
15
  # For rails 3.0 and 3.1
16
16
  if Rails.version < "3.2"
17
- ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::DocumentNotFound'] = :not_found,
18
- ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::InvalidKey'] = :unprocessable_entity,
19
- ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::InvalidScheme'] = :unprocessable_entity,
17
+ ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::DocumentNotFound'] = :not_found
18
+ ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::InvalidKey'] = :unprocessable_entity
19
+ ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::InvalidScheme'] = :unprocessable_entity
20
20
  ActionDispatch::ShowExceptions.rescue_responses['MongoMapper::NotSupported'] = :unprocessable_entity
21
21
  else
22
22
  # For rails 3.2 and 4.0
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module MongoMapper
3
- Version = '0.13.0'
3
+ Version = '0.13.1'
4
4
  end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ module CounterCacheFixtureModels
4
+ class User
5
+ include MongoMapper::Document
6
+
7
+ key :posts_count, Integer, :default => 0
8
+
9
+ has_many :posts,
10
+ :class_name => "CounterCacheFixtureModels::Post"
11
+ end
12
+
13
+ class Post
14
+ include MongoMapper::Document
15
+
16
+ key :comments_count, Integer, :default => 0
17
+ key :some_custom_comments_count, Integer, :default => 0
18
+
19
+ has_many :comments,
20
+ :class_name => "CounterCacheFixtureModels::Comment"
21
+
22
+ belongs_to :user,
23
+ :counter_cache => true,
24
+ :class_name => "CounterCacheFixtureModels::User"
25
+ end
26
+
27
+ class Comment
28
+ include MongoMapper::Document
29
+
30
+ belongs_to :post,
31
+ :counter_cache => true,
32
+ :class_name => "CounterCacheFixtureModels::Post"
33
+ end
34
+
35
+ class CustomComment
36
+ include MongoMapper::Document
37
+
38
+ belongs_to :post,
39
+ :counter_cache => :some_custom_comments_count,
40
+ :class_name => "CounterCacheFixtureModels::Post"
41
+ end
42
+ end
43
+
44
+ describe MongoMapper::Plugins::CounterCache do
45
+ before do
46
+ @post_class = CounterCacheFixtureModels::Post
47
+ @comment_class = CounterCacheFixtureModels::Comment
48
+ @user_class = CounterCacheFixtureModels::User
49
+ @custom_comment_class = CounterCacheFixtureModels::CustomComment
50
+ end
51
+
52
+ it "should have a key with posts_count defaulting to 0" do
53
+ @post_class.new.comments_count.should == 0
54
+ end
55
+
56
+ it "should update the count when a new object is created" do
57
+ post = @post_class.new
58
+ comment = @comment_class.new
59
+
60
+ post.save!
61
+
62
+ comment.post = post
63
+ comment.save!
64
+
65
+ post.reload
66
+ post.comments_count.should == 1
67
+
68
+ second_comment = @comment_class.new
69
+ second_comment.post = post
70
+ second_comment.save!
71
+
72
+ post.reload
73
+ post.comments_count.should == 2
74
+ end
75
+
76
+ it "should decrease the count by one when an object is destroyed" do
77
+ post = @post_class.new
78
+ comment = @comment_class.new
79
+
80
+ post.save!
81
+
82
+ comment.post = post
83
+ comment.save!
84
+
85
+ post.reload
86
+ post.comments_count.should == 1
87
+
88
+ comment.destroy
89
+ post.reload
90
+ post.comments_count.should == 0
91
+ end
92
+
93
+ it "should use the correct association name" do
94
+ @user = @user_class.new
95
+ @post = @post_class.new
96
+
97
+ @user.save!
98
+ @post.user = @user
99
+ @post.save!
100
+
101
+ @user.reload
102
+ @user.posts_count.should == 1
103
+ end
104
+
105
+ it "should be able to use a custom field name" do
106
+ @post = @post_class.new
107
+ @custom_comment = @custom_comment_class.new
108
+
109
+ @post.save!
110
+ @custom_comment.post = @post
111
+ @custom_comment.save!
112
+
113
+ @post.reload
114
+ @post.some_custom_comments_count.should == 1
115
+ end
116
+
117
+ it "should thrown an error if there is no association" do
118
+ lambda {
119
+ CounterCacheFixtureModels.module_eval do
120
+ class CommentWithInvalidAssociation
121
+ include MongoMapper::Document
122
+
123
+ belongs_to :post,
124
+ :class_name => "CounterCacheFixtureModels::Post"
125
+
126
+ counter_cache :foo
127
+ end
128
+ end
129
+ }.should raise_error(MongoMapper::Plugins::CounterCache::InvalidCounterCacheError, "You must define an association with name `foo' on model CommentWithInvalidAssociation")
130
+ end
131
+
132
+ it "should thown a sensible error if the field is not defined on the target object" do
133
+ lambda {
134
+ CounterCacheFixtureModels.module_eval do
135
+ class CommentWithBadRefenceField
136
+ include MongoMapper::Document
137
+
138
+ belongs_to :post,
139
+ :class_name => "CounterCacheFixtureModels::Post"
140
+
141
+ counter_cache :post, :field => :invalid_field
142
+ end
143
+ end
144
+ }.should raise_error(MongoMapper::Plugins::CounterCache::InvalidCounterCacheError, "Missing `key :invalid_field, Integer, :default => 0' on model CounterCacheFixtureModels::Post")
145
+ end
146
+ end
@@ -130,6 +130,34 @@ describe "Document" do
130
130
  end
131
131
  end
132
132
 
133
+ context "symbol key" do
134
+ before do
135
+ @document.key :foo, Symbol, :default => lambda { 123 }
136
+ end
137
+
138
+ it "should return default value" do
139
+ doc = @document.new
140
+ doc.foo.should == :'123'
141
+ end
142
+
143
+ it "should return symbol value" do
144
+ doc = @document.create :foo => 'qwerty'
145
+ doc.foo.should == :qwerty
146
+
147
+ doc.set :foo => 'poiuyt'
148
+ doc.reload
149
+ doc.foo.should == :poiuyt
150
+
151
+ doc.foo = 'asdf'
152
+ doc.foo.should == :asdf
153
+ end
154
+
155
+ it "should return typecasted value" do
156
+ doc = @document.new
157
+ (doc.foo = 'qwerty').should == 'qwerty'
158
+ end
159
+ end
160
+
133
161
  it "should have instance method for collection" do
134
162
  @document.new.collection.name.should == @document.collection.name
135
163
  end
File without changes
@@ -296,4 +296,35 @@ describe "Keys" do
296
296
  end
297
297
  end
298
298
  end
299
+
300
+ describe "removing keys" do
301
+ DocWithRemovedKey = Doc do
302
+ key :something
303
+ validates_uniqueness_of :something
304
+ remove_key :something
305
+ end
306
+
307
+ it 'should remove the key' do
308
+ DocWithRemovedKey.keys.should_not have_key "_something"
309
+ end
310
+
311
+ it 'should remove validations' do
312
+ DocWithRemovedKey._validate_callbacks.should be_empty
313
+ end
314
+ end
315
+
316
+ describe "removing keys in the presence of a validation method" do
317
+ DocWithRemovedValidator = Doc do
318
+ key :something
319
+ validate :something_valid?
320
+ remove_key :something
321
+
322
+ def something_valid?; true; end
323
+ end
324
+
325
+ it 'should remove the key' do
326
+ DocWithRemovedKey.keys.should_not have_key "_something"
327
+ end
328
+
329
+ end
299
330
  end
File without changes
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Stats" do
4
+ before(:each) do
5
+ class ::Docs
6
+ include MongoMapper::Document
7
+ key :title, String
8
+ key :published_at, Time
9
+ end
10
+
11
+ Docs.collection.drop
12
+ end
13
+
14
+ context "with no documents present" do
15
+ it "should return nil" do
16
+ expect(Docs.stats).to eq(nil)
17
+ end
18
+ end
19
+
20
+ context "with documents present" do
21
+ before do
22
+ # Make sure that there is at least one document stored
23
+ Docs.create!
24
+ end
25
+
26
+ it "should have the correct count" do
27
+ expect(Docs.stats.count).to eq(Docs.collection.stats['count'])
28
+ end
29
+
30
+ it "should have the correct namespace" do
31
+ expect(Docs.stats.ns).to eq(Docs.collection.stats['ns'])
32
+ end
33
+
34
+ it "should have the correct size" do
35
+ expect(Docs.stats.size).to eq(Docs.collection.stats['size'])
36
+ end
37
+
38
+ it "should have the correct storage size" do
39
+ expect(Docs.stats.storage_size).to eq(Docs.collection.stats['storageSize'])
40
+ end
41
+
42
+ it "should have the correct average object size" do
43
+ expect(Docs.stats.avg_obj_size).to eq(Docs.collection.stats['avgObjSize'])
44
+ end
45
+
46
+ it "should have the correct number of extents" do
47
+ expect(Docs.stats.num_extents).to eq(Docs.collection.stats['numExtents'])
48
+ end
49
+
50
+ it "should have the correct number of indexes" do
51
+ expect(Docs.stats.nindexes).to eq(Docs.collection.stats['nindexes'])
52
+ end
53
+
54
+ it "should have the correct last extent size" do
55
+ expect(Docs.stats.last_extent_size).to eq(Docs.collection.stats['lastExtentSize'])
56
+ end
57
+
58
+ it "should have the correct padding factor" do
59
+ expect(Docs.stats.padding_factor).to eq(Docs.collection.stats['paddingFactor'])
60
+ end
61
+
62
+ it "should have the correct system flags" do
63
+ expect(Docs.stats.system_flags).to eq(Docs.collection.stats['systemFlags'])
64
+ end
65
+
66
+ it "should have the correct user flags" do
67
+ expect(Docs.stats.user_flags).to eq(Docs.collection.stats['userFlags'])
68
+ end
69
+
70
+ it "should have the correct total index size" do
71
+ expect(Docs.stats.total_index_size).to eq(Docs.collection.stats['totalIndexSize'])
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,51 @@
1
+ if defined?(Encoding) && Encoding.default_external != "UTF-8"
2
+ Encoding.default_external = "UTF-8"
3
+ end
4
+
5
+ describe "The library itself" do
6
+ def check_for_tab_characters(filename)
7
+ failing_lines = []
8
+ File.readlines(filename).each_with_index do |line,number|
9
+ failing_lines << number + 1 if line =~ /\t/
10
+ end
11
+
12
+ unless failing_lines.empty?
13
+ "#{filename} has tab characters on lines #{failing_lines.join(', ')}"
14
+ end
15
+ end
16
+
17
+ def check_for_extra_spaces(filename)
18
+ failing_lines = []
19
+ File.readlines(filename).each_with_index do |line,number|
20
+ next if line =~ /^\s+#.*\s+\n$/
21
+ failing_lines << number + 1 if line =~ /\s+\n$/
22
+ end
23
+
24
+ unless failing_lines.empty?
25
+ "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}"
26
+ end
27
+ end
28
+
29
+ RSpec::Matchers.define :be_well_formed do
30
+ failure_message_for_should do |actual|
31
+ actual.join("\n")
32
+ end
33
+
34
+ match do |actual|
35
+ actual.empty?
36
+ end
37
+ end
38
+
39
+ it "has no malformed whitespace" do
40
+ exempt = /\.gitmodules|\.marshal|fixtures|vendor|ssl_certs|kill|LICENSE/
41
+ error_messages = []
42
+ Dir.chdir(File.expand_path("../..", __FILE__)) do
43
+ `git ls-files`.split("\n").each do |filename|
44
+ next if filename =~ exempt
45
+ error_messages << check_for_tab_characters(filename)
46
+ error_messages << check_for_extra_spaces(filename)
47
+ end
48
+ end
49
+ expect(error_messages.compact).to be_well_formed
50
+ end
51
+ end
@@ -96,5 +96,10 @@ describe "Proxy" do
96
96
  it "should not work if neither the proxy or target respond to method" do
97
97
  lambda { @proxy.send(:gsub) }.should raise_error
98
98
  end
99
+
100
+ it "should work if a proc is passed" do
101
+ p = Proc.new {|x| x+1}
102
+ @proxy.send(:collect, &p).should == [2,3]
103
+ end
99
104
  end
100
105
  end
@@ -391,4 +391,28 @@ describe "Support" do
391
391
  end
392
392
  end
393
393
  end
394
+
395
+ context "Symbol.to_mongo" do
396
+ it "should convert value to_sym" do
397
+ Symbol.to_mongo('asdfasdfasdf').should == :asdfasdfasdf
398
+ end
399
+
400
+ it "should convert string if not string" do
401
+ Symbol.to_mongo(123).should == :'123'
402
+ end
403
+
404
+ it "should return nil for nil" do
405
+ Symbol.to_mongo(nil).should be_nil
406
+ end
407
+ end
408
+
409
+ context "Symbol.from_mongo" do
410
+ it "should convert value to_sym" do
411
+ Symbol.from_mongo(:asdfasdfasdf).should == :asdfasdfasdf
412
+ end
413
+
414
+ it "should return nil for nil" do
415
+ Symbol.from_mongo(nil).should be_nil
416
+ end
417
+ end
394
418
  end
File without changes
File without changes
@@ -66,6 +66,11 @@ describe "Rails integration" do
66
66
  @klass.new(:bar => 'Setting Foo').foo.should == 'Setting Foo'
67
67
  end
68
68
 
69
+ it "should return the type casted value from write attribute" do
70
+ obj = @klass.new
71
+ obj.write_attribute(:foo, true).should == "true"
72
+ end
73
+
69
74
  context '#to_param' do
70
75
  it "should be nil if not persisted" do
71
76
  @klass.new.tap do |doc|
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo_mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-01 00:00:00.000000000 Z
11
+ date: 2014-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
15
- version_requirements: !ruby/object:Gem::Requirement
15
+ requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 3.0.0
20
- requirement: !ruby/object:Gem::Requirement
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
21
23
  requirements:
22
24
  - - '>='
23
25
  - !ruby/object:Gem::Version
24
26
  version: 3.0.0
25
- prerelease: false
26
- type: :runtime
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
- version_requirements: !ruby/object:Gem::Requirement
29
+ requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.0'
34
- requirement: !ruby/object:Gem::Requirement
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
35
37
  requirements:
36
38
  - - '>='
37
39
  - !ruby/object:Gem::Version
38
40
  version: '3.0'
39
- prerelease: false
40
- type: :runtime
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: plucky
43
- version_requirements: !ruby/object:Gem::Requirement
43
+ requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.6.5
48
- requirement: !ruby/object:Gem::Requirement
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
49
51
  requirements:
50
52
  - - ~>
51
53
  - !ruby/object:Gem::Version
52
54
  version: 0.6.5
53
- prerelease: false
54
- type: :runtime
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mongo
57
- version_requirements: !ruby/object:Gem::Requirement
57
+ requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.8'
62
- requirement: !ruby/object:Gem::Requirement
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
63
65
  requirements:
64
66
  - - ~>
65
67
  - !ruby/object:Gem::Version
66
68
  version: '1.8'
67
- prerelease: false
68
- type: :runtime
69
69
  description: MongoMapper is a Object-Document Mapper for Ruby and Rails
70
70
  email:
71
71
  - nunemaker@gmail.com
@@ -112,6 +112,7 @@ files:
112
112
  - lib/mongo_mapper/extensions/ordered_hash.rb
113
113
  - lib/mongo_mapper/extensions/set.rb
114
114
  - lib/mongo_mapper/extensions/string.rb
115
+ - lib/mongo_mapper/extensions/symbol.rb
115
116
  - lib/mongo_mapper/extensions/time.rb
116
117
  - lib/mongo_mapper/locale/en.yml
117
118
  - lib/mongo_mapper/middleware/identity_map.rb
@@ -142,6 +143,7 @@ files:
142
143
  - lib/mongo_mapper/plugins/caching.rb
143
144
  - lib/mongo_mapper/plugins/callbacks.rb
144
145
  - lib/mongo_mapper/plugins/clone.rb
146
+ - lib/mongo_mapper/plugins/counter_cache.rb
145
147
  - lib/mongo_mapper/plugins/dirty.rb
146
148
  - lib/mongo_mapper/plugins/document.rb
147
149
  - lib/mongo_mapper/plugins/dumpable.rb
@@ -168,6 +170,7 @@ files:
168
170
  - lib/mongo_mapper/plugins/sci.rb
169
171
  - lib/mongo_mapper/plugins/scopes.rb
170
172
  - lib/mongo_mapper/plugins/serialization.rb
173
+ - lib/mongo_mapper/plugins/stats.rb
171
174
  - lib/mongo_mapper/plugins/timestamps.rb
172
175
  - lib/mongo_mapper/plugins/touch.rb
173
176
  - lib/mongo_mapper/plugins/userstamps.rb
@@ -198,6 +201,7 @@ files:
198
201
  - spec/functional/binary_spec.rb
199
202
  - spec/functional/caching_spec.rb
200
203
  - spec/functional/callbacks_spec.rb
204
+ - spec/functional/counter_cache_spec.rb
201
205
  - spec/functional/dirty_spec.rb
202
206
  - spec/functional/document_spec.rb
203
207
  - spec/functional/dumpable_spec.rb
@@ -217,10 +221,12 @@ files:
217
221
  - spec/functional/safe_spec.rb
218
222
  - spec/functional/sci_spec.rb
219
223
  - spec/functional/scopes_spec.rb
224
+ - spec/functional/stats_spec.rb
220
225
  - spec/functional/timestamps_spec.rb
221
226
  - spec/functional/touch_spec.rb
222
227
  - spec/functional/userstamps_spec.rb
223
228
  - spec/functional/validations_spec.rb
229
+ - spec/quality_spec.rb
224
230
  - spec/spec_helper.rb
225
231
  - spec/support/matchers.rb
226
232
  - spec/support/models.rb
@@ -258,7 +264,7 @@ homepage: http://mongomapper.com
258
264
  licenses:
259
265
  - MIT
260
266
  metadata: {}
261
- post_install_message:
267
+ post_install_message:
262
268
  rdoc_options: []
263
269
  require_paths:
264
270
  - lib
@@ -273,9 +279,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
273
279
  - !ruby/object:Gem::Version
274
280
  version: '0'
275
281
  requirements: []
276
- rubyforge_project:
282
+ rubyforge_project:
277
283
  rubygems_version: 2.2.2
278
- signing_key:
284
+ signing_key:
279
285
  specification_version: 4
280
286
  summary: A Ruby Object Mapper for Mongo
281
287
  test_files: []