mongodb_model 0.2.8 → 2.0.0
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/Rakefile +3 -4
- data/lib/mongo/model/assignment.rb +4 -2
- data/lib/mongo/model/callbacks.rb +27 -2
- data/lib/mongo/model/conversion.rb +26 -11
- data/lib/mongo/model/crud.rb +52 -9
- data/lib/mongo/model/{file_model.rb → integration/file_model.rb} +1 -1
- data/lib/mongo/model/{validation → integration/validatable}/uniqueness_validator.rb +2 -2
- data/lib/mongo/model/integration/validatable.rb +41 -0
- data/lib/mongo/model/load.rb +59 -0
- data/lib/mongo/model/model.rb +51 -19
- data/lib/mongo/model/query.rb +1 -1
- data/lib/mongo/model/scope.rb +2 -6
- data/lib/mongo/model/spec.rb +0 -3
- data/lib/mongo/model/support/{types.rb → conversions.rb} +9 -23
- data/lib/mongo/model/support.rb +11 -0
- data/lib/mongo/model/validation.rb +14 -34
- data/lib/mongo/model.rb +1 -46
- data/spec/assignment_spec.rb +2 -2
- data/spec/associations_spec.rb +2 -4
- data/spec/attribute_convertors_spec.rb +9 -9
- data/spec/callbacks_spec.rb +161 -34
- data/spec/conversion_spec.rb +18 -18
- data/spec/crud_spec.rb +79 -81
- data/spec/equality_spec.rb +23 -13
- data/spec/{file_model_spec.rb → integration/file_model_spec.rb} +1 -1
- data/spec/integration/validatable_spec.rb +89 -0
- data/spec/misc_spec.rb +6 -6
- data/spec/query_spec.rb +14 -25
- data/spec/scope_spec.rb +10 -10
- data/spec/spec_helper.rb +19 -3
- data/spec/validation_spec.rb +92 -85
- metadata +16 -12
data/Rakefile
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'rake_ext'
|
2
2
|
|
3
|
-
project
|
3
|
+
project \
|
4
4
|
name: "mongodb_model",
|
5
|
-
|
5
|
+
version: '2.0.0',
|
6
6
|
gem: true,
|
7
7
|
summary: "Object Model for MongoDB",
|
8
8
|
|
9
9
|
author: "Alexey Petrushin",
|
10
|
-
homepage: "http://alexeypetrushin.github.com/mongodb_model"
|
11
|
-
)
|
10
|
+
homepage: "http://alexeypetrushin.github.com/mongodb_model"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'mongo/model/support/conversions'
|
2
|
+
|
1
3
|
module Mongo::Model::Assignment
|
2
4
|
class Dsl < BasicObject
|
3
5
|
def initialize model
|
@@ -47,9 +49,9 @@ module Mongo::Model::Assignment
|
|
47
49
|
dsl = ::Mongo::Model::Assignment::Dsl.new self
|
48
50
|
dsl.instance_eval &block
|
49
51
|
else
|
50
|
-
args.size.
|
52
|
+
args.size.must.be_in 2..3
|
51
53
|
attr_name = args.shift
|
52
|
-
attr_name.
|
54
|
+
attr_name.must.be_a Symbol
|
53
55
|
|
54
56
|
if args.first.is_a? Class
|
55
57
|
type, mass_assignment = args
|
@@ -1,8 +1,33 @@
|
|
1
1
|
module Mongo::Model::Callbacks
|
2
2
|
inherit RubyExt::Callbacks
|
3
3
|
|
4
|
+
protected
|
5
|
+
def with_model_callbacks methods, options, models, &block
|
6
|
+
# Firing before callbacks.
|
7
|
+
unless options[:callbacks] == false
|
8
|
+
methods.each do |method|
|
9
|
+
models.each do |model|
|
10
|
+
return false unless model.run_before_callbacks method, method
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
result = block.call
|
16
|
+
|
17
|
+
# Firing after callbacks.
|
18
|
+
unless options[:callbacks] == false
|
19
|
+
methods.reverse.each do |method|
|
20
|
+
models.each do |model|
|
21
|
+
model.run_after_callbacks method, method
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
4
29
|
module ClassMethods
|
5
|
-
[:validate, :create, :update, :save, :
|
30
|
+
[:validate, :create, :update, :save, :delete].each do |method_name|
|
6
31
|
define_method "before_#{method_name}" do |*args, &block|
|
7
32
|
opt = args.extract_options!
|
8
33
|
if block
|
@@ -14,7 +39,7 @@ module Mongo::Model::Callbacks
|
|
14
39
|
end
|
15
40
|
end
|
16
41
|
|
17
|
-
[:validate, :create, :update, :save, :
|
42
|
+
[:validate, :create, :update, :save, :delete, :build].each do |method_name|
|
18
43
|
define_method "after_#{method_name}" do |*args, &block|
|
19
44
|
opt = args.extract_options!
|
20
45
|
if block
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Mongo::Model::Conversion
|
2
2
|
def model_to_json *args, &block
|
3
|
-
|
3
|
+
to_hash(*args, &block).to_json
|
4
4
|
end
|
5
5
|
|
6
6
|
def model_to_xml *args, &block
|
7
|
-
|
7
|
+
to_hash(*args, &block).to_xml
|
8
8
|
end
|
9
9
|
|
10
10
|
alias_method :to_json, :model_to_json
|
@@ -14,24 +14,25 @@ module Mongo::Model::Conversion
|
|
14
14
|
alias_method :to_json, :model_to_json
|
15
15
|
alias_method :to_xml, :model_to_xml
|
16
16
|
|
17
|
-
#
|
17
|
+
# Hack to supress ActiveSupport as_json.
|
18
18
|
alias_method :as_json, :model_to_json
|
19
19
|
alias_method :as_xml, :model_to_xml
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
#
|
24
|
-
|
22
|
+
def to_hash options = {}
|
23
|
+
# return super if args.empty?
|
24
|
+
#
|
25
|
+
# options = args.first
|
25
26
|
|
26
27
|
if profile = options[:profile]
|
27
28
|
raise "no other optins are allowed when using :profile option!" if options.size > 1
|
28
29
|
profile_options = self.class.profiles[profile] || raise("profile :#{profile} not defined for #{self.class}!")
|
29
|
-
|
30
|
+
to_hash profile_options.merge(_profile: profile)
|
30
31
|
else
|
31
32
|
options.validate_options! :only, :except, :methods, :errors, :_profile
|
32
33
|
child_options = options[:_profile] ? {profile: options[:_profile]} : {}
|
33
34
|
|
34
|
-
instance_variables =
|
35
|
+
instance_variables = self.persistent_instance_variable_names
|
35
36
|
|
36
37
|
if only = options[:only]
|
37
38
|
instance_variables &= Array(only).collect{|n| :"@#{n}"}
|
@@ -42,14 +43,14 @@ module Mongo::Model::Conversion
|
|
42
43
|
result = {}
|
43
44
|
instance_variables.each do |iv_name|
|
44
45
|
value = instance_variable_get iv_name
|
45
|
-
value =
|
46
|
+
value = convert_model value, :to_hash, child_options
|
46
47
|
result[iv_name[1.. -1]] = value
|
47
48
|
end
|
48
49
|
|
49
50
|
methods = options[:methods] ? Array(options[:methods]) : []
|
50
51
|
methods.each do |method|
|
51
52
|
value = send method
|
52
|
-
value =
|
53
|
+
value = convert_model value, :to_hash, child_options
|
53
54
|
result[method.to_s] = value
|
54
55
|
end
|
55
56
|
|
@@ -59,11 +60,25 @@ module Mongo::Model::Conversion
|
|
59
60
|
errors.each{|k, v| stringified_errors[k.to_s] = v}
|
60
61
|
result['errors'] = stringified_errors
|
61
62
|
end
|
62
|
-
|
63
|
+
|
63
64
|
result
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
68
|
+
protected
|
69
|
+
def convert_model obj, method, options
|
70
|
+
if obj.respond_to? :collect_with_value
|
71
|
+
# Array or Hash.
|
72
|
+
obj.collect_with_value{|v| convert_model v, method, options}
|
73
|
+
elsif obj.respond_to? method
|
74
|
+
# Model.
|
75
|
+
obj.send method, options
|
76
|
+
else
|
77
|
+
# Simple object.
|
78
|
+
obj
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
67
82
|
module ClassMethods
|
68
83
|
inheritable_accessor :profiles, {}
|
69
84
|
def profile name, options = {}
|
data/lib/mongo/model/crud.rb
CHANGED
@@ -1,4 +1,29 @@
|
|
1
1
|
module Mongo::Model::Crud
|
2
|
+
# Enhancing Mongo::Object CRUD.
|
3
|
+
|
4
|
+
def create_object collection, options
|
5
|
+
with_model_crud_callbacks [:save, :create], options do |mongo_options|
|
6
|
+
super collection, mongo_options
|
7
|
+
true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def update_object collection, options
|
12
|
+
with_model_crud_callbacks [:save, :update], options do |mongo_options|
|
13
|
+
super collection, mongo_options
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete_object collection, options
|
19
|
+
with_model_crud_callbacks [:delete], options do |mongo_options|
|
20
|
+
super collection, mongo_options
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Model CRUD.
|
26
|
+
|
2
27
|
def save options = {}
|
3
28
|
with_collection options do |collection, options|
|
4
29
|
collection.save self, options
|
@@ -9,20 +34,38 @@ module Mongo::Model::Crud
|
|
9
34
|
save(*args) || raise(Mongo::Error, "can't save invalid model (#{self.errors})!")
|
10
35
|
end
|
11
36
|
|
12
|
-
def
|
37
|
+
def delete options = {}
|
13
38
|
with_collection options do |collection, options|
|
14
|
-
collection.
|
39
|
+
collection.delete self, options
|
15
40
|
end
|
16
41
|
end
|
17
42
|
|
18
|
-
def
|
19
|
-
|
43
|
+
def delete! *args
|
44
|
+
delete(*args) || raise(Mongo::Error, "can't delete invalid model #{self.errors}!")
|
20
45
|
end
|
21
46
|
|
22
47
|
def update doc, options = {}
|
23
|
-
|
48
|
+
with_collection options do |collection, options|
|
49
|
+
collection.update({_id: _id}, doc, options)
|
50
|
+
end
|
24
51
|
end
|
25
52
|
|
53
|
+
protected
|
54
|
+
def with_model_crud_callbacks methods, options, &block
|
55
|
+
models = [self] + embedded_models(true)
|
56
|
+
|
57
|
+
return false if (options[:validate] != false) and invalid?(options)
|
58
|
+
|
59
|
+
with_model_callbacks methods, options, models do
|
60
|
+
mongo_options = options.clone
|
61
|
+
mongo_options.delete :validate
|
62
|
+
mongo_options.delete :callbacks
|
63
|
+
|
64
|
+
block.call mongo_options
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
26
69
|
module ClassMethods
|
27
70
|
def build attributes = {}, options = {}, &block
|
28
71
|
model = self.new
|
@@ -43,14 +86,14 @@ module Mongo::Model::Crud
|
|
43
86
|
model
|
44
87
|
end
|
45
88
|
|
46
|
-
def
|
89
|
+
def delete_all selector = {}, options = {}
|
47
90
|
success = true
|
48
|
-
each(selector){|o| success = false unless o.
|
91
|
+
each(selector){|o| success = false unless o.delete options}
|
49
92
|
success
|
50
93
|
end
|
51
94
|
|
52
|
-
def
|
53
|
-
|
95
|
+
def delete_all! selector = {}, options = {}
|
96
|
+
delete_all(selector, options) || raise(Mongo::Error, "can't delete #{selector.inspect}!")
|
54
97
|
end
|
55
98
|
|
56
99
|
def update selector, doc, options = {}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class
|
1
|
+
class Validatable::UniquenessValidator < Validatable::ValidationBase
|
2
2
|
attr_accessor :scope, :case_sensitive
|
3
3
|
|
4
4
|
def initialize(klass, attribute, options={})
|
@@ -18,7 +18,7 @@ class Mongo::Model::UniquenessValidator < Validatable::ValidationBase
|
|
18
18
|
conditions[attribute] = /^#{Regexp.escape(value.to_s)}$/i
|
19
19
|
end
|
20
20
|
|
21
|
-
# Make sure we're not including the current document in the query
|
21
|
+
# Make sure we're not including the current document in the query.
|
22
22
|
conditions[:_id] = {_ne: instance._id} if instance._id
|
23
23
|
|
24
24
|
!klass.exists?(conditions)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Validatable::Model
|
2
|
+
def errors
|
3
|
+
@_errors ||= Validatable::Errors.new
|
4
|
+
end
|
5
|
+
|
6
|
+
protected
|
7
|
+
def run_validations_for_this_model_only
|
8
|
+
self.class.validations.each do |v|
|
9
|
+
if v.respond_to?(:validate)
|
10
|
+
v.validate self
|
11
|
+
elsif v.is_a? Proc
|
12
|
+
v.call self
|
13
|
+
else
|
14
|
+
send v
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
include ::Validatable::Macros
|
21
|
+
|
22
|
+
inheritable_accessor :validations, []
|
23
|
+
|
24
|
+
def validates_uniqueness_of *args
|
25
|
+
add_validations(args, ::Validatable::UniquenessValidator)
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate validation = nil, &block
|
29
|
+
validations.push block || validation
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
def add_validations(args, klass)
|
34
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
35
|
+
args.each do |attribute|
|
36
|
+
new_validation = klass.new self, attribute, options
|
37
|
+
validate new_validation
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'mongo/object'
|
2
|
+
require 'ruby_ext'
|
3
|
+
|
4
|
+
module Mongo::Model; end
|
5
|
+
|
6
|
+
%w(
|
7
|
+
support
|
8
|
+
|
9
|
+
db
|
10
|
+
conversion
|
11
|
+
assignment
|
12
|
+
callbacks
|
13
|
+
validation
|
14
|
+
crud
|
15
|
+
query
|
16
|
+
query_mixin
|
17
|
+
scope
|
18
|
+
attribute_convertors
|
19
|
+
misc
|
20
|
+
model
|
21
|
+
).each{|f| require "mongo/model/#{f}"}
|
22
|
+
|
23
|
+
module Mongo
|
24
|
+
module Model
|
25
|
+
autoload :FileModel, 'mongo/model/integration/file_model'
|
26
|
+
|
27
|
+
inherit \
|
28
|
+
Db,
|
29
|
+
Conversion,
|
30
|
+
Assignment,
|
31
|
+
Callbacks,
|
32
|
+
Validation,
|
33
|
+
Crud,
|
34
|
+
QueryMixin,
|
35
|
+
Scope,
|
36
|
+
AttributeConvertors,
|
37
|
+
Misc
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Mongo.defaults.merge! \
|
42
|
+
convert_underscore_to_dollar: true,
|
43
|
+
batch_size: 50,
|
44
|
+
multi: true,
|
45
|
+
safe: true,
|
46
|
+
generate_id: true
|
47
|
+
|
48
|
+
# Integration with Rails.
|
49
|
+
unless $dont_use_rails
|
50
|
+
require 'mongo/model/integration/rails' if defined? Rails
|
51
|
+
end
|
52
|
+
|
53
|
+
# Integration with Validatable2
|
54
|
+
unless $dont_use_validatable
|
55
|
+
require 'validatable'
|
56
|
+
require 'mongo/model/integration/validatable'
|
57
|
+
require 'mongo/model/integration/validatable/uniqueness_validator'
|
58
|
+
Mongo::Model.inherit Validatable::Model
|
59
|
+
end
|
data/lib/mongo/model/model.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
1
|
module Mongo::Model
|
2
2
|
include Mongo::Object
|
3
3
|
|
4
|
-
attr_accessor :_id, :_class
|
5
|
-
|
6
|
-
def _id?; !!_id end
|
7
|
-
def new?; !_id end
|
8
|
-
alias_method :new_record?, :new?
|
9
|
-
|
10
4
|
inherited do
|
11
5
|
unless is?(Array) or is?(Hash)
|
12
6
|
alias_method :eql?, :model_eql?
|
@@ -14,6 +8,8 @@ module Mongo::Model
|
|
14
8
|
end
|
15
9
|
end
|
16
10
|
|
11
|
+
# Equality.
|
12
|
+
|
17
13
|
def model_eql? o
|
18
14
|
return true if equal? o
|
19
15
|
self.class == o.class and self == o
|
@@ -21,22 +17,58 @@ module Mongo::Model
|
|
21
17
|
|
22
18
|
def model_eq? o
|
23
19
|
return true if equal? o
|
20
|
+
return false unless o.is_a? Mongo::Model
|
24
21
|
|
25
|
-
variables = {}
|
26
|
-
|
22
|
+
variables = {}.tap do |h|
|
23
|
+
persistent_instance_variable_names.each{|n| h[n] = instance_variable_get(n)}
|
24
|
+
end
|
25
|
+
|
26
|
+
o_variables = {}.tap do |h|
|
27
|
+
o.persistent_instance_variable_names.each{|n| h[n] = o.instance_variable_get(n)}
|
28
|
+
end
|
27
29
|
|
28
30
|
variables == o_variables
|
29
31
|
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
protected
|
34
|
+
# Traversing models.
|
35
|
+
|
36
|
+
def embedded_models recursive = false
|
37
|
+
[].tap{|a| each_embedded(recursive){|m| a.add m}}
|
38
|
+
end
|
39
|
+
|
40
|
+
def each_embedded recursive = false, &block
|
41
|
+
self.class.embedded.each do |name|
|
42
|
+
if o = instance_variable_get(name)
|
43
|
+
_each_embedded o, recursive, &block
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Hash or Array also can be the Model by itsef, so we need to check
|
49
|
+
# for presence both `:each_embedded` and `:each_value` methods.
|
50
|
+
def _each_embedded o, recursive, &block
|
51
|
+
# If o is model adding it and its children.
|
52
|
+
if o.respond_to? :each_embedded
|
53
|
+
block.call o
|
54
|
+
o.each_embedded recursive, &block if recursive
|
55
|
+
end
|
56
|
+
|
57
|
+
# If o is Hash or Array, iterating and adding all models from there,
|
58
|
+
# recursivelly, hashes and arrays can be nested in any order.
|
59
|
+
if o.respond_to? :each_value
|
60
|
+
o.each_value do |o|
|
61
|
+
_each_embedded o, recursive, &block
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module ClassMethods
|
67
|
+
inheritable_accessor :_embedded, []
|
68
|
+
|
69
|
+
def embedded *list
|
70
|
+
list.collect!{|n| :"@#{n}"}
|
71
|
+
if list.empty? then _embedded else _embedded.push(*list) end
|
72
|
+
end
|
73
|
+
end
|
42
74
|
end
|
data/lib/mongo/model/query.rb
CHANGED
data/lib/mongo/model/scope.rb
CHANGED
@@ -53,10 +53,8 @@ module Mongo::Model::Scope
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
# Finders.
|
56
57
|
|
57
|
-
#
|
58
|
-
# finders
|
59
|
-
#
|
60
58
|
def count selector = {}, options = {}
|
61
59
|
if current = current_scope
|
62
60
|
super current.selector.merge(selector), current.options.merge(options)
|
@@ -81,10 +79,8 @@ module Mongo::Model::Scope
|
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
82
|
+
# Shortcuts for frequently used scopes.
|
84
83
|
|
85
|
-
#
|
86
|
-
# Handy scopes
|
87
|
-
#
|
88
84
|
def limit n; query({}, limit: n) end
|
89
85
|
def skip n; query({}, skip: n) end
|
90
86
|
def sort *list
|
data/lib/mongo/model/spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
|
1
|
+
# Converting basic Ruby types to and from String, needed
|
2
|
+
# in mass assignment.
|
3
|
+
|
4
|
+
# Boolean.
|
4
5
|
module Mongo::Model::BooleanType
|
5
6
|
Mapping = {
|
6
7
|
true => true,
|
@@ -37,10 +38,7 @@ class Boolean; end unless defined?(Boolean)
|
|
37
38
|
|
38
39
|
Boolean.extend Mongo::Model::BooleanType
|
39
40
|
|
40
|
-
|
41
|
-
#
|
42
|
-
# Date
|
43
|
-
#
|
41
|
+
# Date.
|
44
42
|
require 'date'
|
45
43
|
Date.class_eval do
|
46
44
|
def self.cast value
|
@@ -55,20 +53,14 @@ Date.class_eval do
|
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
58
|
-
|
59
|
-
#
|
60
|
-
# Float
|
61
|
-
#
|
56
|
+
# Float.
|
62
57
|
Float.class_eval do
|
63
58
|
def self.cast value
|
64
59
|
value.nil? ? nil : value.to_f
|
65
60
|
end
|
66
61
|
end
|
67
62
|
|
68
|
-
|
69
|
-
#
|
70
|
-
# Integer
|
71
|
-
#
|
63
|
+
# Integer.
|
72
64
|
Integer.class_eval do
|
73
65
|
def self.cast value
|
74
66
|
value_to_i = value.to_i
|
@@ -80,20 +72,14 @@ Integer.class_eval do
|
|
80
72
|
end
|
81
73
|
end
|
82
74
|
|
83
|
-
|
84
|
-
#
|
85
|
-
# String
|
86
|
-
#
|
75
|
+
# String.
|
87
76
|
String.class_eval do
|
88
77
|
def self.cast value
|
89
78
|
value.nil? ? nil : value.to_s
|
90
79
|
end
|
91
80
|
end
|
92
81
|
|
93
|
-
|
94
|
-
#
|
95
|
-
# Time
|
96
|
-
#
|
82
|
+
# Time.
|
97
83
|
Time.class_eval do
|
98
84
|
def self.cast value
|
99
85
|
if value.nil? || value == ''
|
@@ -1,41 +1,21 @@
|
|
1
1
|
module Mongo::Model::Validation
|
2
|
-
def
|
3
|
-
|
2
|
+
def valid? options = {}
|
3
|
+
errors.clear
|
4
|
+
run_validations options
|
4
5
|
end
|
6
|
+
def invalid?(options = {}); !valid?(options) end
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
else
|
13
|
-
send v
|
14
|
-
end
|
15
|
-
end
|
16
|
-
true
|
17
|
-
end
|
8
|
+
protected
|
9
|
+
def run_validations options = {}
|
10
|
+
with_model_callbacks [:validate], options, [self] do
|
11
|
+
# Validating main model.
|
12
|
+
self.run_validations_for_this_model_only
|
13
|
+
result = errors.empty?
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
inheritable_accessor :validations, []
|
23
|
-
|
24
|
-
def validates_uniqueness_of *args
|
25
|
-
add_validations(args, Mongo::Model::UniquenessValidator)
|
26
|
-
end
|
27
|
-
|
28
|
-
def validate validation = nil, &block
|
29
|
-
validations.push block || validation
|
30
|
-
end
|
31
|
-
|
32
|
-
protected
|
33
|
-
def add_validations(args, klass)
|
34
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
35
|
-
args.each do |attribute|
|
36
|
-
new_validation = klass.new self, attribute, options
|
37
|
-
validate new_validation
|
15
|
+
# Validating embedded models.
|
16
|
+
embedded_models.reduce result do |result, model|
|
17
|
+
result &= model.valid?(options)
|
38
18
|
end
|
39
19
|
end
|
40
|
-
|
20
|
+
end
|
41
21
|
end
|