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.
- 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: []
|