mongodb_model 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mongo/model.rb +2 -1
- data/lib/mongo/model/assignment.rb +25 -28
- data/lib/mongo/model/conversion.rb +67 -0
- data/lib/mongo/model/crud.rb +8 -0
- data/lib/mongo/model/misc.rb +0 -7
- data/lib/mongo/model/model.rb +2 -2
- data/lib/mongo/model/query_mixin.rb +3 -2
- data/lib/mongo/model/scope.rb +13 -0
- data/lib/mongodb_model/gems.rb +1 -1
- data/spec/assignment_spec.rb +2 -1
- data/spec/callbacks_spec.rb +1 -1
- data/spec/conversion_spec.rb +101 -0
- data/spec/crud_spec.rb +12 -0
- data/spec/scope_spec.rb +14 -0
- metadata +12 -21
data/lib/mongo/model.rb
CHANGED
@@ -2,7 +2,6 @@ require 'mongodb_model/gems'
|
|
2
2
|
|
3
3
|
require 'validatable'
|
4
4
|
require 'file_model'
|
5
|
-
require 'i18n'
|
6
5
|
require 'ruby_ext'
|
7
6
|
require 'mongo/object'
|
8
7
|
|
@@ -12,6 +11,7 @@ module Mongo::Model; end
|
|
12
11
|
support/types
|
13
12
|
|
14
13
|
db
|
14
|
+
conversion
|
15
15
|
assignment
|
16
16
|
callbacks
|
17
17
|
validation
|
@@ -30,6 +30,7 @@ module Mongo
|
|
30
30
|
module Model
|
31
31
|
inherit \
|
32
32
|
Db,
|
33
|
+
Conversion,
|
33
34
|
Assignment,
|
34
35
|
Callbacks,
|
35
36
|
Validation,
|
@@ -1,32 +1,13 @@
|
|
1
1
|
module Mongo::Model::Assignment
|
2
2
|
class Dsl < BasicObject
|
3
|
-
def initialize
|
4
|
-
@
|
3
|
+
def initialize model
|
4
|
+
@model = model
|
5
5
|
end
|
6
6
|
|
7
|
-
def self.const_missing name
|
8
|
-
# BasicObject doesn't have access to any constants like String, Symbol, ...
|
9
|
-
::Object.const_get name
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_h; attributes end
|
13
|
-
|
14
7
|
protected
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
attribute_name.must_be.a Symbol
|
19
|
-
|
20
|
-
args.size.must_be.in 1..2
|
21
|
-
if args.first.is_a? Class
|
22
|
-
type, mass_assignment = args
|
23
|
-
mass_assignment ||= false
|
24
|
-
type.must.respond_to :cast
|
25
|
-
else
|
26
|
-
type, mass_assignment = nil, args.first
|
27
|
-
end
|
28
|
-
|
29
|
-
attributes[attribute_name] = [type, mass_assignment]
|
8
|
+
def method_missing m, *args
|
9
|
+
args.unshift m
|
10
|
+
@model.assign *args
|
30
11
|
end
|
31
12
|
end
|
32
13
|
|
@@ -61,10 +42,26 @@ module Mongo::Model::Assignment
|
|
61
42
|
module ClassMethods
|
62
43
|
inheritable_accessor :_assign, nil
|
63
44
|
|
64
|
-
def assign &block
|
65
|
-
|
66
|
-
|
67
|
-
|
45
|
+
def assign *args, &block
|
46
|
+
if block
|
47
|
+
dsl = ::Mongo::Model::Assignment::Dsl.new self
|
48
|
+
dsl.instance_eval &block
|
49
|
+
else
|
50
|
+
args.size.must_be.in 2..3
|
51
|
+
attr_name = args.shift
|
52
|
+
attr_name.must_be.a Symbol
|
53
|
+
|
54
|
+
if args.first.is_a? Class
|
55
|
+
type, mass_assignment = args
|
56
|
+
mass_assignment ||= false
|
57
|
+
type.must.respond_to :cast
|
58
|
+
else
|
59
|
+
type, mass_assignment = nil, args.first
|
60
|
+
end
|
61
|
+
|
62
|
+
self._assign ||= {}
|
63
|
+
_assign[attr_name] = [type, mass_assignment]
|
64
|
+
end
|
68
65
|
end
|
69
66
|
end
|
70
67
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Mongo::Model::Conversion
|
2
|
+
def model_to_json *args, &block
|
3
|
+
to_rson(*args, &block).to_json
|
4
|
+
end
|
5
|
+
|
6
|
+
def model_to_xml *args, &block
|
7
|
+
to_rson(*args, &block).to_xml
|
8
|
+
end
|
9
|
+
|
10
|
+
alias_method :to_json, :model_to_json
|
11
|
+
alias_method :to_xml, :model_to_xml
|
12
|
+
|
13
|
+
inherited do
|
14
|
+
alias_method :to_json, :model_to_json
|
15
|
+
alias_method :to_xml, :model_to_xml
|
16
|
+
|
17
|
+
# hack to supress ActiveSupport as_json
|
18
|
+
alias_method :as_json, :model_to_json
|
19
|
+
alias_method :as_xml, :model_to_xml
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_rson options = {}
|
23
|
+
# hack to suppress ActiveSupport as_json
|
24
|
+
options ||= {}
|
25
|
+
|
26
|
+
if profile = options[:profile]
|
27
|
+
raise "no other optins are allowed when using :profile option!" if options.size > 1
|
28
|
+
profile_options = self.class.profiles[profile] || raise("profile :#{profile} not defined for #{self.class}!")
|
29
|
+
to_rson profile_options.merge(_profile: profile)
|
30
|
+
else
|
31
|
+
options.validate_options! :only, :except, :methods, :_profile
|
32
|
+
child_options = options[:_profile] ? {profile: options[:_profile]} : {}
|
33
|
+
|
34
|
+
instance_variables = Mongo::Object.instance_variables(self)
|
35
|
+
|
36
|
+
if only = options[:only]
|
37
|
+
instance_variables &= Array(only).collect{|n| :"@#{n}"}
|
38
|
+
elsif except = options[:except]
|
39
|
+
instance_variables -= Array(except).collect{|n| :"@#{n}"}
|
40
|
+
end
|
41
|
+
|
42
|
+
result = {}
|
43
|
+
instance_variables.each do |iv_name|
|
44
|
+
value = instance_variable_get iv_name
|
45
|
+
value = Mongo::Object.convert value, :to_rson, child_options
|
46
|
+
result[iv_name[1.. -1]] = value
|
47
|
+
end
|
48
|
+
|
49
|
+
methods = options[:methods] ? Array(options[:methods]) : []
|
50
|
+
|
51
|
+
methods.each do |method|
|
52
|
+
value = send method
|
53
|
+
value = Mongo::Object.convert value, :to_rson, child_options
|
54
|
+
result[method.to_s] = value
|
55
|
+
end
|
56
|
+
|
57
|
+
result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module ClassMethods
|
62
|
+
inheritable_accessor :profiles, {}
|
63
|
+
def profile name, options = {}
|
64
|
+
profiles[name] = options
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/mongo/model/crud.rb
CHANGED
@@ -19,6 +19,10 @@ module Mongo::Model::Crud
|
|
19
19
|
destroy(*args) || raise(Mongo::Error, "can't destroy invalid model #{self.errors}!")
|
20
20
|
end
|
21
21
|
|
22
|
+
def update doc, options = {}
|
23
|
+
self.class.collection.update({_id: _id}, doc, options)
|
24
|
+
end
|
25
|
+
|
22
26
|
module ClassMethods
|
23
27
|
def build attributes = {}, options = {}, &block
|
24
28
|
model = self.new
|
@@ -49,6 +53,10 @@ module Mongo::Model::Crud
|
|
49
53
|
def destroy_all! selector = {}, options = {}
|
50
54
|
destroy_all(selector, options) || raise(Mongo::Error, "can't destroy #{selector.inspect}!")
|
51
55
|
end
|
56
|
+
|
57
|
+
def update selector, doc, options = {}
|
58
|
+
collection.update selector, doc, options
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
54
62
|
protected
|
data/lib/mongo/model/misc.rb
CHANGED
@@ -12,9 +12,6 @@ module Mongo::Model::Misc
|
|
12
12
|
def _cache
|
13
13
|
@_cache ||= {}
|
14
14
|
end
|
15
|
-
# def _clear_cache
|
16
|
-
# @_cache = {}
|
17
|
-
# end
|
18
15
|
|
19
16
|
def dom_id
|
20
17
|
# new_record? ? "new_#{self.class.name.underscore}" : to_param
|
@@ -25,8 +22,6 @@ module Mongo::Model::Misc
|
|
25
22
|
(_id || '').to_s
|
26
23
|
end
|
27
24
|
|
28
|
-
delegate :t, to: I18n
|
29
|
-
|
30
25
|
def reload
|
31
26
|
obj = self.class.by_id!(_id || raise("can't reload new document (#{self})!"))
|
32
27
|
instance_variables.each{|n| remove_instance_variable n}
|
@@ -41,8 +36,6 @@ module Mongo::Model::Misc
|
|
41
36
|
end
|
42
37
|
|
43
38
|
module ClassMethods
|
44
|
-
delegate :t, to: I18n
|
45
|
-
|
46
39
|
def timestamps!
|
47
40
|
attr_accessor :created_at, :updated_at
|
48
41
|
before_create :update_created_at
|
data/lib/mongo/model/model.rb
CHANGED
@@ -19,8 +19,8 @@ module Mongo::Model
|
|
19
19
|
def model_eq? o
|
20
20
|
return true if equal? o
|
21
21
|
|
22
|
-
variables = {}; ::Mongo::Object.
|
23
|
-
o_variables = {}; ::Mongo::Object.
|
22
|
+
variables = {}; ::Mongo::Object.each_instance_variable(self){|n, v| variables[n] = v}
|
23
|
+
o_variables = {}; ::Mongo::Object.each_instance_variable(o){|n, v| o_variables[n] = v}
|
24
24
|
|
25
25
|
variables == o_variables
|
26
26
|
end
|
@@ -2,7 +2,7 @@ module Mongo::Model::QueryMixin
|
|
2
2
|
def exists? options = {}
|
3
3
|
self.class.count({_id: _id}, options) > 0
|
4
4
|
end
|
5
|
-
|
5
|
+
alias_method :exist?, :exists?
|
6
6
|
|
7
7
|
module ClassMethods
|
8
8
|
include Mongo::DynamicFinders
|
@@ -36,7 +36,7 @@ module Mongo::Model::QueryMixin
|
|
36
36
|
def exists? selector = {}, options = {}
|
37
37
|
count(selector, options) > 0
|
38
38
|
end
|
39
|
-
|
39
|
+
alias_method :exist?, :exists?
|
40
40
|
|
41
41
|
def query *args
|
42
42
|
if args.first.is_a? Mongo::Model::Query
|
@@ -46,5 +46,6 @@ module Mongo::Model::QueryMixin
|
|
46
46
|
Mongo::Model::Query.new self, (selector || {}), (options || {})
|
47
47
|
end
|
48
48
|
end
|
49
|
+
alias_method :where, :query
|
49
50
|
end
|
50
51
|
end
|
data/lib/mongo/model/scope.rb
CHANGED
@@ -81,6 +81,19 @@ module Mongo::Model::Scope
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
|
85
|
+
#
|
86
|
+
# Handy scopes
|
87
|
+
#
|
88
|
+
def limit n; query({}, limit: n) end
|
89
|
+
def skip n; query({}, skip: n) end
|
90
|
+
def sort *list; query({}, sort: list) end
|
91
|
+
def snapshot; query({}, snapshot: true) end
|
92
|
+
|
93
|
+
def paginate page, per_page
|
94
|
+
skip((page - 1) * per_page).limit(per_page)
|
95
|
+
end
|
96
|
+
|
84
97
|
protected
|
85
98
|
def scope_identifier
|
86
99
|
@scope_identifier ||= :"mms_#{self.name}"
|
data/lib/mongodb_model/gems.rb
CHANGED
data/spec/assignment_spec.rb
CHANGED
data/spec/callbacks_spec.rb
CHANGED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Model callbacks' do
|
4
|
+
with_mongo_model
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
class BasePost
|
8
|
+
inherit Mongo::Model
|
9
|
+
|
10
|
+
attr_accessor :text, :token
|
11
|
+
|
12
|
+
attr_writer :comments
|
13
|
+
def comments; @comments ||= [] end
|
14
|
+
|
15
|
+
def teaser
|
16
|
+
@text && @text[0..10]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class BaseComment
|
21
|
+
inherit Mongo::Model
|
22
|
+
|
23
|
+
attr_accessor :text
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
before do
|
28
|
+
class Post < BasePost; end
|
29
|
+
class Comment < BaseComment; end
|
30
|
+
end
|
31
|
+
|
32
|
+
after{remove_constants :Post, :Comment}
|
33
|
+
after(:all){remove_constants :BasePost, :BaseComment}
|
34
|
+
|
35
|
+
def build_post_with_comment
|
36
|
+
post = Post.new text: 'StarCraft releasing soon!', token: 'secret'
|
37
|
+
post.comments << Comment.new(text: 'Cool!')
|
38
|
+
post
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should work without arguments" do
|
42
|
+
post = build_post_with_comment
|
43
|
+
post.to_rson.should == {
|
44
|
+
'text' => 'StarCraft releasing soon!',
|
45
|
+
'token' => 'secret',
|
46
|
+
'comments' => [
|
47
|
+
{'text' => 'Cool!'}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
it "only, except, methods" do
|
53
|
+
post = build_post_with_comment
|
54
|
+
post.to_rson(only: :text).should == {'text' => 'StarCraft releasing soon!'}
|
55
|
+
post.to_rson(except: :token).should == {
|
56
|
+
'text' => 'StarCraft releasing soon!',
|
57
|
+
'comments' => [
|
58
|
+
{'text' => 'Cool!'}
|
59
|
+
]
|
60
|
+
}
|
61
|
+
post.to_rson(only: [], methods: :teaser).should == {'teaser' => 'StarCraft r'}
|
62
|
+
end
|
63
|
+
|
64
|
+
it "profiles" do
|
65
|
+
Post.class_eval do
|
66
|
+
profile :public, only: [:text, :comments], methods: :teaser
|
67
|
+
end
|
68
|
+
|
69
|
+
post = build_post_with_comment
|
70
|
+
|
71
|
+
-> {post.to_rson(profile: :public)}.should raise_error(/profile :public not defined for Comment/)
|
72
|
+
|
73
|
+
Comment.class_eval do
|
74
|
+
profile :public
|
75
|
+
end
|
76
|
+
|
77
|
+
post.to_rson(profile: :public).should == {
|
78
|
+
'text' => 'StarCraft releasing soon!',
|
79
|
+
'teaser' => 'StarCraft r',
|
80
|
+
'comments' => [
|
81
|
+
{'text' => 'Cool!'}
|
82
|
+
]
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
it "to_json" do
|
87
|
+
post = build_post_with_comment
|
88
|
+
rson = mock
|
89
|
+
rson.should_receive(:to_json).and_return(:ok)
|
90
|
+
post.should_receive(:to_rson).with(only: :text).and_return(rson)
|
91
|
+
post.to_json(only: :text).should == :ok
|
92
|
+
end
|
93
|
+
|
94
|
+
it "to_xml" do
|
95
|
+
post = build_post_with_comment
|
96
|
+
rson = mock
|
97
|
+
rson.should_receive(:to_xml).and_return(:ok)
|
98
|
+
post.should_receive(:to_rson).with(only: :text).and_return(rson)
|
99
|
+
post.to_xml(only: :text).should == :ok
|
100
|
+
end
|
101
|
+
end
|
data/spec/crud_spec.rb
CHANGED
@@ -93,6 +93,18 @@ describe "Model CRUD" do
|
|
93
93
|
|
94
94
|
Unit.destroy_all!
|
95
95
|
end
|
96
|
+
|
97
|
+
it 'modifiers' do
|
98
|
+
unit = Unit.create! name: 'Zeratul'
|
99
|
+
|
100
|
+
Unit.update({_id: unit._id}, _set: {name: 'Tassadar'})
|
101
|
+
unit.reload
|
102
|
+
unit.name.should == 'Tassadar'
|
103
|
+
|
104
|
+
unit.update _set: {name: 'Fenix'}
|
105
|
+
unit.reload
|
106
|
+
unit.name.should == 'Fenix'
|
107
|
+
end
|
96
108
|
end
|
97
109
|
|
98
110
|
describe 'embedded' do
|
data/spec/scope_spec.rb
CHANGED
@@ -147,4 +147,18 @@ describe "Scope" do
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
end
|
150
|
+
|
151
|
+
describe 'handy scopes' do
|
152
|
+
it "limit, skip, sort" do
|
153
|
+
query = Unit.skip(30).limit(10).sort([name: 1]).snapshot
|
154
|
+
query.selector.should == {}
|
155
|
+
query.options.should == {skip: 30, limit: 10, sort: [[name: 1]], snapshot: true}
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'paginate' do
|
159
|
+
query = Unit.paginate(4, 10)
|
160
|
+
query.selector.should == {}
|
161
|
+
query.options.should == {skip: 30, limit: 10}
|
162
|
+
end
|
163
|
+
end
|
150
164
|
end
|
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: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
date: 2011-09-06 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: i18n
|
16
|
-
requirement: &2781050 !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0.5'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: *2781050
|
25
14
|
- !ruby/object:Gem::Dependency
|
26
15
|
name: mongodb
|
27
|
-
requirement: &
|
16
|
+
requirement: &2839010 !ruby/object:Gem::Requirement
|
28
17
|
none: false
|
29
18
|
requirements:
|
30
19
|
- - ! '>='
|
@@ -32,10 +21,10 @@ dependencies:
|
|
32
21
|
version: '0'
|
33
22
|
type: :runtime
|
34
23
|
prerelease: false
|
35
|
-
version_requirements: *
|
24
|
+
version_requirements: *2839010
|
36
25
|
- !ruby/object:Gem::Dependency
|
37
26
|
name: file_model
|
38
|
-
requirement: &
|
27
|
+
requirement: &2845520 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
29
|
requirements:
|
41
30
|
- - ! '>='
|
@@ -43,10 +32,10 @@ dependencies:
|
|
43
32
|
version: '0'
|
44
33
|
type: :runtime
|
45
34
|
prerelease: false
|
46
|
-
version_requirements: *
|
35
|
+
version_requirements: *2845520
|
47
36
|
- !ruby/object:Gem::Dependency
|
48
37
|
name: validatable2
|
49
|
-
requirement: &
|
38
|
+
requirement: &2846710 !ruby/object:Gem::Requirement
|
50
39
|
none: false
|
51
40
|
requirements:
|
52
41
|
- - ! '>='
|
@@ -54,10 +43,10 @@ dependencies:
|
|
54
43
|
version: '0'
|
55
44
|
type: :runtime
|
56
45
|
prerelease: false
|
57
|
-
version_requirements: *
|
46
|
+
version_requirements: *2846710
|
58
47
|
- !ruby/object:Gem::Dependency
|
59
48
|
name: ruby_ext
|
60
|
-
requirement: &
|
49
|
+
requirement: &2847870 !ruby/object:Gem::Requirement
|
61
50
|
none: false
|
62
51
|
requirements:
|
63
52
|
- - ! '>='
|
@@ -65,7 +54,7 @@ dependencies:
|
|
65
54
|
version: '0'
|
66
55
|
type: :runtime
|
67
56
|
prerelease: false
|
68
|
-
version_requirements: *
|
57
|
+
version_requirements: *2847870
|
69
58
|
description:
|
70
59
|
email:
|
71
60
|
executables: []
|
@@ -77,6 +66,7 @@ files:
|
|
77
66
|
- lib/mongo/model/assignment.rb
|
78
67
|
- lib/mongo/model/attribute_convertors.rb
|
79
68
|
- lib/mongo/model/callbacks.rb
|
69
|
+
- lib/mongo/model/conversion.rb
|
80
70
|
- lib/mongo/model/crud.rb
|
81
71
|
- lib/mongo/model/db.rb
|
82
72
|
- lib/mongo/model/file_model.rb
|
@@ -95,6 +85,7 @@ files:
|
|
95
85
|
- spec/associations_spec.rb
|
96
86
|
- spec/attribute_convertors_spec.rb
|
97
87
|
- spec/callbacks_spec.rb
|
88
|
+
- spec/conversion_spec.rb
|
98
89
|
- spec/crud_spec.rb
|
99
90
|
- spec/db_spec.rb
|
100
91
|
- spec/equality_spec.rb
|