mongodb_model 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/mongo/model/conversion.rb +9 -6
- data/lib/mongo/model/crud.rb +5 -2
- data/lib/mongo/model/identity_map.rb +2 -2
- data/lib/mongo/model/integration/rad.rb +27 -1
- data/lib/mongo/model/integration/rails.rb +2 -2
- data/lib/mongo/model/integration/validatable/uniqueness_validator.rb +1 -1
- data/lib/mongo/model/misc.rb +3 -3
- data/lib/mongo/model/query_mixin.rb +1 -1
- data/lib/mongo/model/scope.rb +92 -89
- data/spec/associations_spec.rb +1 -1
- data/spec/conversion_spec.rb +8 -5
- data/spec/crud_spec.rb +9 -4
- data/spec/misc_spec.rb +1 -1
- data/spec/query_spec.rb +1 -1
- metadata +8 -8
@@ -21,13 +21,14 @@ module Mongo::Model::Conversion
|
|
21
21
|
alias_method :as_xml, :model_to_xml
|
22
22
|
end
|
23
23
|
|
24
|
-
def to_rson options = {}
|
24
|
+
def to_rson options = {}, &block
|
25
25
|
options = {profile: options} if options.is_a? Symbol
|
26
26
|
|
27
27
|
if profile = options[:profile]
|
28
28
|
raise "no other optins are allowed when using :profile option!" if options.size > 1
|
29
|
-
|
30
|
-
|
29
|
+
meta = self.class.profiles[profile] || raise("profile :#{profile} not defined for #{self.class}!")
|
30
|
+
profile_options, profile_block = meta
|
31
|
+
to_rson profile_options.merge(_profile: profile), &profile_block
|
31
32
|
else
|
32
33
|
options.validate_options! :only, :except, :methods, :errors, :id, :_profile
|
33
34
|
child_options = options[:_profile] ? {profile: options[:_profile]} : {}
|
@@ -61,7 +62,9 @@ module Mongo::Model::Conversion
|
|
61
62
|
result[:errors] = errors
|
62
63
|
end
|
63
64
|
|
64
|
-
result[:id] =
|
65
|
+
result[:id] = id if id and (options[:id] != false)
|
66
|
+
|
67
|
+
instance_exec result, &block if block
|
65
68
|
|
66
69
|
result
|
67
70
|
end
|
@@ -69,8 +72,8 @@ module Mongo::Model::Conversion
|
|
69
72
|
|
70
73
|
module ClassMethods
|
71
74
|
inheritable_accessor :profiles, {}
|
72
|
-
def profile name, options = {}
|
73
|
-
profiles[name] = options
|
75
|
+
def profile name, options = {}, &block
|
76
|
+
profiles[name] = [options, block]
|
74
77
|
end
|
75
78
|
end
|
76
79
|
end
|
data/lib/mongo/model/crud.rb
CHANGED
@@ -46,7 +46,7 @@ module Mongo::Model::Crud
|
|
46
46
|
|
47
47
|
def update doc, options = {}
|
48
48
|
with_collection options do |collection, options|
|
49
|
-
collection.update({
|
49
|
+
collection.update({id: id}, doc, options)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -104,7 +104,10 @@ module Mongo::Model::Crud
|
|
104
104
|
protected
|
105
105
|
def with_collection options, &block
|
106
106
|
options = options.clone
|
107
|
-
collection = options.delete(:collection)
|
107
|
+
if collection = options.delete(:collection)
|
108
|
+
collection = self.class.db.collection collection if collection.is_a?(Symbol)
|
109
|
+
end
|
110
|
+
collection ||= self.class.collection
|
108
111
|
block.call collection, options
|
109
112
|
end
|
110
113
|
end
|
@@ -6,7 +6,7 @@ module Mongo::Model::IdentityMap
|
|
6
6
|
def original
|
7
7
|
unless _cache[:original_cached]
|
8
8
|
_cache[:original_cached] = true
|
9
|
-
_cache[:original] =
|
9
|
+
_cache[:original] = id && self.class.get_from_identity_map(id)
|
10
10
|
end
|
11
11
|
_cache[:original]
|
12
12
|
end
|
@@ -23,7 +23,7 @@ module Mongo::Model::IdentityMap
|
|
23
23
|
|
24
24
|
def from_mongo doc
|
25
25
|
model = super doc
|
26
|
-
model.class.identity_map[model.
|
26
|
+
model.class.identity_map[model.id] = doc if model.id
|
27
27
|
model
|
28
28
|
end
|
29
29
|
end
|
@@ -12,7 +12,33 @@ rad.register :models do
|
|
12
12
|
Mongo::Model::Component.new
|
13
13
|
end
|
14
14
|
|
15
|
-
#
|
15
|
+
# Connection settings defined in the `models.yml` config file for the :models component.
|
16
|
+
#
|
17
|
+
# Sample of `models.yml` config file, it cotains database names and connection settings.
|
18
|
+
#
|
19
|
+
# db:
|
20
|
+
# default:
|
21
|
+
# host: localhost
|
22
|
+
# port: 4029
|
23
|
+
# name: my_web_app
|
24
|
+
# tmp:
|
25
|
+
# name: all_sorts_of_tmp_data
|
26
|
+
#
|
27
|
+
# Note that we use logical name of the database, the real name can be different. It gives You flexibility and
|
28
|
+
# allows You to use the same logical name, but it can mean different databases with different real names in
|
29
|
+
# let's say :development and :production evnironments:
|
30
|
+
#
|
31
|
+
# Usage - if not specified the :default alias will be used:
|
32
|
+
#
|
33
|
+
# class Blog
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# You can also explicitly specify what alias should be used:
|
37
|
+
#
|
38
|
+
# class Token
|
39
|
+
# db :tmp
|
40
|
+
# end
|
41
|
+
#
|
16
42
|
Mongo.metaclass_eval do
|
17
43
|
def db name
|
18
44
|
config = rad.models.db[name.to_s] || raise("no database config for #{name} alias!")
|
@@ -19,7 +19,7 @@ class Validatable::UniquenessValidator < Validatable::ValidationBase
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# Make sure we're not including the current document in the query.
|
22
|
-
conditions[:_id] = {_ne: instance.
|
22
|
+
conditions[:_id] = {_ne: instance.id} if instance.id
|
23
23
|
|
24
24
|
!klass.exists?(conditions)
|
25
25
|
end
|
data/lib/mongo/model/misc.rb
CHANGED
@@ -18,11 +18,11 @@ module Mongo::Model::Misc
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def to_param
|
21
|
-
|
21
|
+
id.try :to_s
|
22
22
|
end
|
23
23
|
|
24
24
|
def reload
|
25
|
-
obj = self.class.by_id!(
|
25
|
+
obj = self.class.by_id!(id || raise("can't reload new document (#{self})!"))
|
26
26
|
instance_variables.each{|n| remove_instance_variable n}
|
27
27
|
obj.instance_variables.each do |n|
|
28
28
|
instance_variable_set n, obj.instance_variable_get(n)
|
@@ -33,7 +33,7 @@ module Mongo::Model::Misc
|
|
33
33
|
def original
|
34
34
|
unless _cache[:original_cached]
|
35
35
|
_cache[:original_cached] = true
|
36
|
-
_cache[:original] =
|
36
|
+
_cache[:original] = id && self.class.by_id(id)
|
37
37
|
end
|
38
38
|
_cache[:original]
|
39
39
|
end
|
data/lib/mongo/model/scope.rb
CHANGED
@@ -1,113 +1,116 @@
|
|
1
|
-
module Mongo::Model
|
2
|
-
|
3
|
-
def current_scope
|
4
|
-
scope, exclusive = Thread.current[scope_identifier]
|
5
|
-
current = if exclusive
|
6
|
-
scope
|
7
|
-
elsif scope
|
8
|
-
default_scope ? default_scope.merge(scope) : scope
|
9
|
-
else
|
10
|
-
default_scope
|
11
|
-
end
|
12
|
-
end
|
1
|
+
module Mongo::Model
|
2
|
+
PER_PAGE, MAX_PER_PAGE = 25, 100
|
13
3
|
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
module Scope
|
5
|
+
module ClassMethods
|
6
|
+
def current_scope
|
7
|
+
scope, exclusive = Thread.current[scope_identifier]
|
8
|
+
current = if exclusive
|
9
|
+
scope
|
10
|
+
elsif scope
|
11
|
+
default_scope ? default_scope.merge(scope) : scope
|
12
|
+
else
|
13
|
+
default_scope
|
14
|
+
end
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
exclusive = args.pop
|
21
|
-
else
|
22
|
-
exclusive = false
|
17
|
+
def with_exclusive_scope *args, &block
|
18
|
+
with_scope *(args << true), &block
|
23
19
|
end
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
def with_scope *args, &block
|
22
|
+
if args.last.is_a?(TrueClass) or args.last.is_a?(FalseClass)
|
23
|
+
exclusive = args.pop
|
24
|
+
else
|
25
|
+
exclusive = false
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
scope = query *args
|
29
|
+
previous_scope, previous_exclusive = Thread.current[scope_identifier]
|
30
|
+
raise "exclusive scope already applied!" if previous_exclusive
|
31
|
+
|
32
|
+
begin
|
33
|
+
scope = previous_scope.merge scope if !exclusive and previous_scope
|
34
|
+
Thread.current[scope_identifier] = [scope, exclusive]
|
35
|
+
return block.call
|
36
|
+
ensure
|
37
|
+
Thread.current[scope_identifier] = [previous_scope, false]
|
38
|
+
end
|
35
39
|
end
|
36
|
-
end
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
inheritable_accessor :_default_scope, nil
|
42
|
+
def default_scope *args, &block
|
43
|
+
if block
|
44
|
+
self._default_scope = -> {query block.call}
|
45
|
+
elsif !args.empty?
|
46
|
+
self._default_scope = -> {query *args}
|
47
|
+
else
|
48
|
+
_default_scope && _default_scope.call
|
49
|
+
end
|
46
50
|
end
|
47
|
-
end
|
48
51
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
def scope name, *args, &block
|
53
|
+
model = self
|
54
|
+
metaclass.define_method name do
|
55
|
+
query (block && instance_eval(&block)) || args
|
56
|
+
end
|
53
57
|
end
|
54
|
-
end
|
55
58
|
|
56
|
-
|
59
|
+
# Finders.
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
def count selector = {}, options = {}
|
62
|
+
if current = current_scope
|
63
|
+
super current.selector.merge(selector), current.options.merge(options)
|
64
|
+
else
|
65
|
+
super selector, options
|
66
|
+
end
|
63
67
|
end
|
64
|
-
end
|
65
68
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
69
|
+
def first selector = {}, options = {}
|
70
|
+
if current = current_scope
|
71
|
+
super current.selector.merge(selector), current.options.merge(options)
|
72
|
+
else
|
73
|
+
super selector, options
|
74
|
+
end
|
71
75
|
end
|
72
|
-
end
|
73
76
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
77
|
+
def each selector = {}, options = {}, &block
|
78
|
+
if current = current_scope
|
79
|
+
super current.selector.merge(selector), current.options.merge(options), &block
|
80
|
+
else
|
81
|
+
super selector, options, &block
|
82
|
+
end
|
79
83
|
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Shortcuts for frequently used scopes.
|
83
84
|
|
84
|
-
|
85
|
-
def skip n; query({}, skip: n) end
|
86
|
-
def sort *list
|
87
|
-
list = list.collect{|item| item.is_a?(Array) ? item : [item, 1]}
|
88
|
-
query({}, sort: list)
|
89
|
-
end
|
90
|
-
alias_method :sort_by, :sort
|
91
|
-
def snapshot; query({}, snapshot: true) end
|
85
|
+
# Shortcuts for frequently used scopes.
|
92
86
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
else
|
99
|
-
options = args.first
|
100
|
-
page, per_page = options[:page], options[:per_page]
|
87
|
+
def limit n; query({}, limit: n) end
|
88
|
+
def skip n; query({}, skip: n) end
|
89
|
+
def sort *list
|
90
|
+
list = list.collect{|item| item.is_a?(Array) ? item : [item, 1]}
|
91
|
+
query({}, sort: list)
|
101
92
|
end
|
102
|
-
|
103
|
-
|
104
|
-
per_page = MAX_PER_PAGE if per_page > MAX_PER_PAGE
|
105
|
-
skip((page - 1) * per_page).limit(per_page)
|
106
|
-
end
|
93
|
+
alias_method :sort_by, :sort
|
94
|
+
def snapshot; query({}, snapshot: true) end
|
107
95
|
|
108
|
-
|
109
|
-
|
110
|
-
|
96
|
+
def paginate *args
|
97
|
+
args.size.must.be_in 1..2
|
98
|
+
if args.size == 2
|
99
|
+
page, per_page = *args
|
100
|
+
else
|
101
|
+
options = args.first
|
102
|
+
page, per_page = options[:page].try(:to_i), options[:per_page].try(:to_i)
|
103
|
+
end
|
104
|
+
page ||= 1
|
105
|
+
per_page ||= PER_PAGE
|
106
|
+
per_page = MAX_PER_PAGE if per_page > MAX_PER_PAGE
|
107
|
+
skip((page - 1) * per_page).limit(per_page)
|
111
108
|
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
def scope_identifier
|
112
|
+
@scope_identifier ||= :"mms_#{self.name}"
|
113
|
+
end
|
114
|
+
end
|
112
115
|
end
|
113
116
|
end
|
data/spec/associations_spec.rb
CHANGED
data/spec/conversion_spec.rb
CHANGED
@@ -49,11 +49,12 @@ describe 'Conversion' do
|
|
49
49
|
}
|
50
50
|
end
|
51
51
|
|
52
|
-
it "should accept :only, :except
|
52
|
+
it "should accept :only, :except, :methods options and block" do
|
53
53
|
post = build_post_with_comment
|
54
54
|
post.to_rson(only: :text).should == {text: 'StarCraft releasing soon!'}
|
55
|
-
post.to_rson(except: :token).should == {
|
55
|
+
post.to_rson(except: :token){|data| data[:type] = 'Post'}.should == {
|
56
56
|
text: 'StarCraft releasing soon!',
|
57
|
+
type: 'Post',
|
57
58
|
comments: [
|
58
59
|
{text: 'Cool!'}
|
59
60
|
]
|
@@ -71,14 +72,16 @@ describe 'Conversion' do
|
|
71
72
|
-> {post.to_rson(profile: :public)}.should raise_error(/profile :public not defined for Comment/)
|
72
73
|
|
73
74
|
Comment.class_eval do
|
74
|
-
profile :public
|
75
|
+
profile :public do |data|
|
76
|
+
data[:type] = 'Comment'
|
77
|
+
end
|
75
78
|
end
|
76
79
|
|
77
80
|
post.to_rson(profile: :public).should == {
|
78
81
|
text: 'StarCraft releasing soon!',
|
79
82
|
teaser: 'StarCraft r',
|
80
83
|
comments: [
|
81
|
-
{text: 'Cool!'}
|
84
|
+
{text: 'Cool!', type: 'Comment'}
|
82
85
|
]
|
83
86
|
}
|
84
87
|
|
@@ -86,7 +89,7 @@ describe 'Conversion' do
|
|
86
89
|
text: 'StarCraft releasing soon!',
|
87
90
|
teaser: 'StarCraft r',
|
88
91
|
comments: [
|
89
|
-
{text: 'Cool!'}
|
92
|
+
{text: 'Cool!', type: 'Comment'}
|
90
93
|
]
|
91
94
|
}
|
92
95
|
end
|
data/spec/crud_spec.rb
CHANGED
@@ -47,7 +47,7 @@ describe "Model CRUD" do
|
|
47
47
|
|
48
48
|
# Create.
|
49
49
|
@unit.save.should be_true
|
50
|
-
@unit.
|
50
|
+
@unit.id.should_not be_nil
|
51
51
|
|
52
52
|
# Read.
|
53
53
|
Unit.count.should == 1
|
@@ -69,7 +69,7 @@ describe "Model CRUD" do
|
|
69
69
|
it 'should be able to save model to another collection' do
|
70
70
|
# Create.
|
71
71
|
@unit.save(collection: db.heroes).should be_true
|
72
|
-
@unit.
|
72
|
+
@unit.id.should_not be_nil
|
73
73
|
|
74
74
|
# Read.
|
75
75
|
Unit.count.should == 0
|
@@ -89,6 +89,11 @@ describe "Model CRUD" do
|
|
89
89
|
db.heroes.count.should == 0
|
90
90
|
end
|
91
91
|
|
92
|
+
it 'should be able to save model to another collection (defined as symbol)' do
|
93
|
+
@unit.save(collection: :heroes).should be_true
|
94
|
+
db.heroes.first.should == @unit
|
95
|
+
end
|
96
|
+
|
92
97
|
it 'should build model' do
|
93
98
|
u = Unit.build name: 'Zeratul'
|
94
99
|
u.name.should == 'Zeratul'
|
@@ -111,7 +116,7 @@ describe "Model CRUD" do
|
|
111
116
|
it 'should accept modifiers' do
|
112
117
|
unit = Unit.create! name: 'Zeratul'
|
113
118
|
|
114
|
-
Unit.update({
|
119
|
+
Unit.update({id: unit.id}, _set: {name: 'Tassadar'})
|
115
120
|
unit.reload
|
116
121
|
unit.name.should == 'Tassadar'
|
117
122
|
|
@@ -152,7 +157,7 @@ describe "Model CRUD" do
|
|
152
157
|
it 'should perform CRUD' do
|
153
158
|
# Create.
|
154
159
|
@unit.save.should be_true
|
155
|
-
@unit.
|
160
|
+
@unit.id.should_not be_nil
|
156
161
|
|
157
162
|
# Read.
|
158
163
|
Unit.count.should == 1
|
data/spec/misc_spec.rb
CHANGED
@@ -85,7 +85,7 @@ describe 'Miscellaneous' do
|
|
85
85
|
unit = Unit.first
|
86
86
|
unit.name = "Tassadar"
|
87
87
|
|
88
|
-
Unit.should_receive(:first).with(_id: unit.
|
88
|
+
Unit.should_receive(:first).with(_id: unit.id).and_return{db.units.first(id: unit.id)}
|
89
89
|
unit.original.name.should == "Zeratul"
|
90
90
|
end
|
91
91
|
|
data/spec/query_spec.rb
CHANGED
@@ -43,7 +43,7 @@ describe "Query" do
|
|
43
43
|
u = Unit.build(name: 'Zeratul')
|
44
44
|
u.save!
|
45
45
|
Unit.first_by_name('Zeratul').name.should == 'Zeratul'
|
46
|
-
Unit.by_id!(u.
|
46
|
+
Unit.by_id!(u.id).name.should == 'Zeratul'
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'should be integrated with build, create and create!' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongodb_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-05 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongodb
|
16
|
-
requirement: &
|
16
|
+
requirement: &70263477501940 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70263477501940
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: validatable2
|
27
|
-
requirement: &
|
27
|
+
requirement: &70263477501460 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70263477501460
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: ruby_ext
|
38
|
-
requirement: &
|
38
|
+
requirement: &70263477500960 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70263477500960
|
47
47
|
description:
|
48
48
|
email:
|
49
49
|
executables: []
|