mongo_mapper 0.13.0 → 0.13.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.
- checksums.yaml +4 -4
- data/lib/mongo_mapper.rb +3 -0
- data/lib/mongo_mapper/connection.rb +4 -3
- data/lib/mongo_mapper/document.rb +2 -0
- data/lib/mongo_mapper/extensions/symbol.rb +18 -0
- data/lib/mongo_mapper/plugins/accessible.rb +10 -1
- data/lib/mongo_mapper/plugins/associations/base.rb +5 -1
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +9 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +0 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +0 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +0 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +0 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +2 -2
- data/lib/mongo_mapper/plugins/counter_cache.rb +78 -0
- data/lib/mongo_mapper/plugins/indexes.rb +0 -0
- data/lib/mongo_mapper/plugins/keys.rb +14 -2
- data/lib/mongo_mapper/plugins/modifiers.rb +0 -0
- data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +0 -0
- data/lib/mongo_mapper/plugins/rails.rb +1 -0
- data/lib/mongo_mapper/plugins/sci.rb +0 -0
- data/lib/mongo_mapper/plugins/stats.rb +19 -0
- data/lib/mongo_mapper/plugins/validations.rb +1 -1
- data/lib/mongo_mapper/railtie.rb +3 -3
- data/lib/mongo_mapper/version.rb +1 -1
- data/spec/functional/counter_cache_spec.rb +146 -0
- data/spec/functional/document_spec.rb +28 -0
- data/spec/functional/indexes_spec.rb +0 -0
- data/spec/functional/keys_spec.rb +31 -0
- data/spec/functional/sci_spec.rb +0 -0
- data/spec/functional/stats_spec.rb +74 -0
- data/spec/quality_spec.rb +51 -0
- data/spec/unit/associations/proxy_spec.rb +5 -0
- data/spec/unit/extensions_spec.rb +24 -0
- data/spec/unit/key_spec.rb +0 -0
- data/spec/unit/model_generator_spec.rb +0 -0
- data/spec/unit/rails_spec.rb +5 -0
- metadata +28 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e78985587a63e18283384630db3c316ee260b20
|
4
|
+
data.tar.gz: 5f2d55cbe5df4c2f8322088cb9f0edfaa84a69e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
84
|
+
klass.new( env['hosts'], options )
|
84
85
|
else
|
85
|
-
|
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|
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -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
|
-
|
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.
|
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
|
File without changes
|
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
|
data/lib/mongo_mapper/railtie.rb
CHANGED
@@ -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
|
data/lib/mongo_mapper/version.rb
CHANGED
@@ -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
|
data/spec/functional/sci_spec.rb
CHANGED
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
|
data/spec/unit/key_spec.rb
CHANGED
File without changes
|
File without changes
|
data/spec/unit/rails_spec.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2014-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
15
|
-
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 3.0.0
|
20
|
-
|
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
|
-
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '3.0'
|
34
|
-
|
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
|
-
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 0.6.5
|
48
|
-
|
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
|
-
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1.8'
|
62
|
-
|
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: []
|