mongodb_model 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/mongo/model/assignment.rb +2 -1
- data/lib/mongo/model/conversion.rb +15 -23
- data/lib/mongo/model/db.rb +13 -1
- data/lib/mongo/model/identity_map.rb +38 -0
- data/lib/mongo/model/integration/rad/tasks.rb +10 -0
- data/lib/mongo/model/integration/rad.rb +41 -0
- data/lib/mongo/model/integration/rails.rb +2 -0
- data/lib/mongo/model/load.rb +10 -8
- data/lib/mongo/model/misc.rb +9 -2
- data/lib/mongo/model/model.rb +12 -0
- data/lib/mongo/model/scope.rb +13 -1
- data/lib/mongo/model/spec.rb +6 -0
- data/lib/mongo/model/support/rson.rb +68 -0
- data/lib/mongo/model/validation.rb +31 -0
- data/lib/mongo/model.rb +2 -0
- data/lib/mongodb_model/gems.rb +0 -3
- data/spec/assignment_spec.rb +4 -1
- data/spec/attribute_convertors_spec.rb +2 -1
- data/spec/callbacks_spec.rb +1 -1
- data/spec/conversion_spec.rb +22 -14
- data/spec/crud_spec.rb +20 -4
- data/spec/misc_spec.rb +47 -6
- data/spec/query_spec.rb +3 -1
- data/spec/validation_spec.rb +22 -0
- metadata +13 -10
- data/lib/mongo/model/support.rb +0 -10
data/Rakefile
CHANGED
@@ -23,7 +23,8 @@ module Mongo::Model::Assignment
|
|
23
23
|
v = type.cast(v) if type
|
24
24
|
send "#{n}=", v
|
25
25
|
else
|
26
|
-
|
26
|
+
# Do nothing, just silently skip it.
|
27
|
+
# raise "mass assignment for :#{n} attribute not allowed!"
|
27
28
|
end
|
28
29
|
end
|
29
30
|
else
|
@@ -1,10 +1,12 @@
|
|
1
|
+
require 'mongo/model/support/rson'
|
2
|
+
|
1
3
|
module Mongo::Model::Conversion
|
2
4
|
def model_to_json *args, &block
|
3
|
-
|
5
|
+
to_rson(*args, &block).to_json
|
4
6
|
end
|
5
7
|
|
6
8
|
def model_to_xml *args, &block
|
7
|
-
|
9
|
+
to_rson(*args, &block).to_xml
|
8
10
|
end
|
9
11
|
|
10
12
|
alias_method :to_json, :model_to_json
|
@@ -19,13 +21,15 @@ module Mongo::Model::Conversion
|
|
19
21
|
alias_method :as_xml, :model_to_xml
|
20
22
|
end
|
21
23
|
|
22
|
-
def
|
24
|
+
def to_rson options = {}
|
25
|
+
options = {profile: options} if options.is_a? Symbol
|
26
|
+
|
23
27
|
if profile = options[:profile]
|
24
28
|
raise "no other optins are allowed when using :profile option!" if options.size > 1
|
25
29
|
profile_options = self.class.profiles[profile] || raise("profile :#{profile} not defined for #{self.class}!")
|
26
|
-
|
30
|
+
to_rson profile_options.merge(_profile: profile)
|
27
31
|
else
|
28
|
-
options.validate_options! :only, :except, :methods, :errors, :_profile
|
32
|
+
options.validate_options! :only, :except, :methods, :errors, :id, :_profile
|
29
33
|
child_options = options[:_profile] ? {profile: options[:_profile]} : {}
|
30
34
|
|
31
35
|
instance_variables = self.persistent_instance_variable_names
|
@@ -39,15 +43,15 @@ module Mongo::Model::Conversion
|
|
39
43
|
result = {}
|
40
44
|
instance_variables.each do |iv_name|
|
41
45
|
value = instance_variable_get iv_name
|
42
|
-
value =
|
43
|
-
result[iv_name[1.. -1].to_sym] = value
|
46
|
+
# value = convert_object value, :to_rson, child_options
|
47
|
+
result[iv_name[1.. -1].to_sym] = value.to_rson child_options
|
44
48
|
end
|
45
49
|
|
46
50
|
methods = options[:methods] ? Array(options[:methods]) : []
|
47
51
|
methods.each do |method|
|
48
52
|
value = send method
|
49
|
-
value =
|
50
|
-
result[method.to_sym] = value
|
53
|
+
# value = convert_object value, :to_rson, child_options
|
54
|
+
result[method.to_sym] = value.to_rson child_options
|
51
55
|
end
|
52
56
|
|
53
57
|
with_errors = options.include?(:errors) ? options[:errors] : true
|
@@ -57,24 +61,12 @@ module Mongo::Model::Conversion
|
|
57
61
|
result[:errors] = errors
|
58
62
|
end
|
59
63
|
|
64
|
+
result[:id] = _id if _id and (options[:id] != false)
|
65
|
+
|
60
66
|
result
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
64
|
-
protected
|
65
|
-
def convert_model obj, method, options
|
66
|
-
if obj.respond_to? :collect_with_value
|
67
|
-
# Array or Hash.
|
68
|
-
obj.collect_with_value{|v| convert_model v, method, options}
|
69
|
-
elsif obj.respond_to? method
|
70
|
-
# Model.
|
71
|
-
obj.send method, options
|
72
|
-
else
|
73
|
-
# Simple object.
|
74
|
-
obj
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
70
|
module ClassMethods
|
79
71
|
inheritable_accessor :profiles, {}
|
80
72
|
def profile name, options = {}
|
data/lib/mongo/model/db.rb
CHANGED
@@ -22,7 +22,19 @@ module Mongo::Model::Db
|
|
22
22
|
def default_collection_name
|
23
23
|
first_ancestor_class = ancestors.find{|a| a.is_a? Class} ||
|
24
24
|
raise("can't evaluate default collection name for #{self}!")
|
25
|
-
first_ancestor_class.alias
|
25
|
+
als = first_ancestor_class.alias
|
26
|
+
|
27
|
+
unless als.respond_to? :pluralize
|
28
|
+
warn <<-TEXT
|
29
|
+
WARN: It seems that there's no `String.pluralize` method, Mongo::Model needs it to automatically infer
|
30
|
+
collection name from the model class name.
|
31
|
+
Please specify collection name explicitly (like `collection :users`) or provide the `pluralize`
|
32
|
+
method.
|
33
|
+
TEXT
|
34
|
+
raise "collection name for #{first_ancestor_class} not defined (add it, like `collection :users`)!"
|
35
|
+
end
|
36
|
+
|
37
|
+
als.pluralize.underscore.to_sym
|
26
38
|
end
|
27
39
|
end
|
28
40
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Mongo::Model::IdentityMap
|
2
|
+
inherited do
|
3
|
+
Mongo::Model::IdentityMap.models.add self
|
4
|
+
end
|
5
|
+
|
6
|
+
def original
|
7
|
+
unless _cache[:original_cached]
|
8
|
+
_cache[:original_cached] = true
|
9
|
+
_cache[:original] = _id && self.class.get_from_identity_map(_id)
|
10
|
+
end
|
11
|
+
_cache[:original]
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def identity_map
|
16
|
+
@identity_map ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_from_identity_map id
|
20
|
+
doc = identity_map[id]
|
21
|
+
from_mongo doc if doc
|
22
|
+
end
|
23
|
+
|
24
|
+
def from_mongo doc
|
25
|
+
model = super doc
|
26
|
+
model.class.identity_map[model._id] = doc if model._id
|
27
|
+
model
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def models
|
33
|
+
@models ||= Set.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def clear; models.collect(&:identity_map).every.clear end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'mongo/migration/tasks'
|
2
|
+
|
3
|
+
namespace :db do
|
4
|
+
desc "Internal task to prepare migration environment"
|
5
|
+
task migration_evnironment: :environment do
|
6
|
+
require 'mongo/migration'
|
7
|
+
|
8
|
+
Dir["#{rad.runtime_path}/db/**/*.rb"].each{|f| require f.sub(/\.rb$/, '')}
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Registering it as component.
|
2
|
+
|
3
|
+
class Mongo::Model::Component
|
4
|
+
attr_accessor :db
|
5
|
+
attr_required :db
|
6
|
+
|
7
|
+
attr_accessor :fs
|
8
|
+
attr_required :fs
|
9
|
+
end
|
10
|
+
|
11
|
+
rad.register :models do
|
12
|
+
Mongo::Model::Component.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# Using DB connection setting defined in component's config file.
|
16
|
+
Mongo.metaclass_eval do
|
17
|
+
def db name
|
18
|
+
config = rad.models.db[name.to_s] || raise("no database config for #{name} alias!")
|
19
|
+
host, port, options = config['host'], config['port'], (config['options'] || {})
|
20
|
+
connection = self.connection host, port, options
|
21
|
+
db_name = config['name'] || raise("no database name for #{name} alias!")
|
22
|
+
connection.db db_name
|
23
|
+
end
|
24
|
+
cache_method_with_params :db
|
25
|
+
|
26
|
+
def connection host, port, options
|
27
|
+
options[:logger] = rad.logger unless options.include? :logger
|
28
|
+
Mongo::Connection.new host, port, options
|
29
|
+
end
|
30
|
+
cache_method_with_params :connection
|
31
|
+
end
|
32
|
+
|
33
|
+
# Localization
|
34
|
+
|
35
|
+
Mongo::Model::Misc.class_eval do
|
36
|
+
def t *args; rad.locale.t *args end
|
37
|
+
end
|
38
|
+
|
39
|
+
Mongo::Model::Misc::ClassMethods.class_eval do
|
40
|
+
def t *args; rad.locale.t *args end
|
41
|
+
end
|
data/lib/mongo/model/load.rb
CHANGED
@@ -1,17 +1,14 @@
|
|
1
|
-
require 'mongo/object'
|
2
1
|
require 'ruby_ext'
|
3
2
|
|
4
3
|
module Mongo::Model; end
|
5
4
|
|
6
5
|
%w(
|
7
|
-
support
|
8
|
-
|
9
6
|
db
|
10
7
|
conversion
|
11
8
|
assignment
|
12
9
|
callbacks
|
13
|
-
validation
|
14
10
|
crud
|
11
|
+
validation
|
15
12
|
query
|
16
13
|
query_mixin
|
17
14
|
scope
|
@@ -20,17 +17,18 @@ module Mongo::Model; end
|
|
20
17
|
model
|
21
18
|
).each{|f| require "mongo/model/#{f}"}
|
22
19
|
|
20
|
+
# Assembling model.
|
23
21
|
module Mongo
|
24
22
|
module Model
|
25
|
-
autoload :
|
23
|
+
autoload :IdentityMap, 'mongo/model/identity_map'
|
26
24
|
|
27
25
|
inherit \
|
28
26
|
Db,
|
29
27
|
Conversion,
|
30
28
|
Assignment,
|
31
29
|
Callbacks,
|
32
|
-
Validation,
|
33
30
|
Crud,
|
31
|
+
Validation,
|
34
32
|
QueryMixin,
|
35
33
|
Scope,
|
36
34
|
AttributeConvertors,
|
@@ -45,15 +43,19 @@ Mongo.defaults.merge! \
|
|
45
43
|
safe: true,
|
46
44
|
generate_id: true
|
47
45
|
|
48
|
-
#
|
46
|
+
# Integrations.
|
47
|
+
|
49
48
|
unless $dont_use_rails
|
50
49
|
require 'mongo/model/integration/rails' if defined? Rails
|
51
50
|
end
|
52
51
|
|
53
|
-
# Integration with Validatable2
|
54
52
|
unless $dont_use_validatable
|
55
53
|
require 'validatable'
|
56
54
|
require 'mongo/model/integration/validatable'
|
57
55
|
require 'mongo/model/integration/validatable/uniqueness_validator'
|
58
56
|
Mongo::Model.inherit Validatable::Model
|
57
|
+
end
|
58
|
+
|
59
|
+
unless $dont_use_file_model
|
60
|
+
Mongo::Model.autoload :FileModel, 'mongo/model/integration/file_model'
|
59
61
|
end
|
data/lib/mongo/model/misc.rb
CHANGED
@@ -8,7 +8,6 @@ module Mongo::Model::Misc
|
|
8
8
|
self.updated_at = now
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
11
|
def _cache
|
13
12
|
@_cache ||= {}
|
14
13
|
end
|
@@ -32,7 +31,11 @@ module Mongo::Model::Misc
|
|
32
31
|
end
|
33
32
|
|
34
33
|
def original
|
35
|
-
|
34
|
+
unless _cache[:original_cached]
|
35
|
+
_cache[:original_cached] = true
|
36
|
+
_cache[:original] = _id && self.class.by_id(_id)
|
37
|
+
end
|
38
|
+
_cache[:original]
|
36
39
|
end
|
37
40
|
|
38
41
|
module ClassMethods
|
@@ -41,5 +44,9 @@ module Mongo::Model::Misc
|
|
41
44
|
before_create :update_created_at
|
42
45
|
before_save :update_updated_at
|
43
46
|
end
|
47
|
+
|
48
|
+
def create_index *args
|
49
|
+
collection.create_index *args
|
50
|
+
end
|
44
51
|
end
|
45
52
|
end
|
data/lib/mongo/model/model.rb
CHANGED
@@ -70,5 +70,17 @@ module Mongo::Model
|
|
70
70
|
list.collect!{|n| :"@#{n}"}
|
71
71
|
if list.empty? then _embedded else _embedded.push(*list) end
|
72
72
|
end
|
73
|
+
|
74
|
+
def from_mongo doc
|
75
|
+
model = ::Mongo::Object.from_mongo doc
|
76
|
+
model.run_after_callbacks :build, :build
|
77
|
+
model
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class << self
|
82
|
+
def originals
|
83
|
+
@originals ||= {}
|
84
|
+
end
|
73
85
|
end
|
74
86
|
end
|
data/lib/mongo/model/scope.rb
CHANGED
@@ -87,9 +87,21 @@ module Mongo::Model::Scope
|
|
87
87
|
list = list.collect{|item| item.is_a?(Array) ? item : [item, 1]}
|
88
88
|
query({}, sort: list)
|
89
89
|
end
|
90
|
+
alias_method :sort_by, :sort
|
90
91
|
def snapshot; query({}, snapshot: true) end
|
91
92
|
|
92
|
-
|
93
|
+
PER_PAGE, MAX_PER_PAGE = 25, 100
|
94
|
+
def paginate *args
|
95
|
+
args.size.must.be_in 1..2
|
96
|
+
if args.size == 2
|
97
|
+
page, per_page = *args
|
98
|
+
else
|
99
|
+
options = args.first
|
100
|
+
page, per_page = options[:page], options[:per_page]
|
101
|
+
end
|
102
|
+
page ||= 1
|
103
|
+
per_page ||= PER_PAGE
|
104
|
+
per_page = MAX_PER_PAGE if per_page > MAX_PER_PAGE
|
93
105
|
skip((page - 1) * per_page).limit(per_page)
|
94
106
|
end
|
95
107
|
|
data/lib/mongo/model/spec.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
class Object
|
2
|
+
def rson?
|
3
|
+
false
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
[
|
8
|
+
Time,
|
9
|
+
FalseClass,
|
10
|
+
TrueClass,
|
11
|
+
Numeric,
|
12
|
+
Symbol,
|
13
|
+
String,
|
14
|
+
NilClass,
|
15
|
+
].each do |klass|
|
16
|
+
klass.class_eval do
|
17
|
+
def to_rson options = {}
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def rson?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# [
|
28
|
+
# String
|
29
|
+
# ].each do |klass|
|
30
|
+
# klass.class_eval do
|
31
|
+
# def to_rson options = {}
|
32
|
+
# self.to_sym
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# def rson?
|
36
|
+
# false
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
|
41
|
+
Array.class_eval do
|
42
|
+
def to_rson options = {}
|
43
|
+
collect{|v| v.to_rson(options)}
|
44
|
+
end
|
45
|
+
|
46
|
+
def rson?
|
47
|
+
all?{|v| v.rson?}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
[Hash, OpenObject].each do |klass|
|
52
|
+
klass.class_eval do
|
53
|
+
def to_rson options = {}
|
54
|
+
r = self.class.new
|
55
|
+
each do |k, v|
|
56
|
+
r[k.to_sym] = v.to_rson(options)
|
57
|
+
end
|
58
|
+
r
|
59
|
+
end
|
60
|
+
|
61
|
+
def rson?
|
62
|
+
each do |k, v|
|
63
|
+
return false unless k.rson? and v.rson?
|
64
|
+
end
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -5,7 +5,38 @@ module Mongo::Model::Validation
|
|
5
5
|
end
|
6
6
|
def invalid?(options = {}); !valid?(options) end
|
7
7
|
|
8
|
+
# Catching erros during CRUD and adding it to errors, like unique index.
|
9
|
+
|
10
|
+
def create_object *args
|
11
|
+
with_exceptions_as_errors do
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_object *args
|
17
|
+
with_exceptions_as_errors do
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete_object *args
|
23
|
+
with_exceptions_as_errors do
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
8
28
|
protected
|
29
|
+
def with_exceptions_as_errors &block
|
30
|
+
block.call
|
31
|
+
rescue Mongo::OperationFailure => e
|
32
|
+
if [11000, 11001].include? e.error_code
|
33
|
+
errors.add :base, "not unique value!"
|
34
|
+
false
|
35
|
+
else
|
36
|
+
raise e
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
9
40
|
def run_validations options = {}
|
10
41
|
with_model_callbacks [:validate], options, [self] do
|
11
42
|
# Validating main model.
|
data/lib/mongo/model.rb
CHANGED
data/lib/mongodb_model/gems.rb
CHANGED
data/spec/assignment_spec.rb
CHANGED
@@ -38,9 +38,12 @@ describe 'Attribute assignment' do
|
|
38
38
|
|
39
39
|
u = User.new
|
40
40
|
u.set name: 'Alex', has_mail: '1', age: '31', position: [11, 34]
|
41
|
-
-> {u.set name: 'Alex', banned: false}.should raise_error(/not allowed/)
|
42
41
|
[u.name, u.has_mail, u.age, u.position, u.banned].should == ['Alex', true, 31, [11, 34], nil]
|
43
42
|
|
43
|
+
# Should skip not allowed attributes.
|
44
|
+
u.set banned: false
|
45
|
+
u.banned.should be_nil
|
46
|
+
|
44
47
|
# should allow to forcefully cast and update any attribute
|
45
48
|
u.set! banned: '0'
|
46
49
|
u.banned.should == false
|
data/spec/callbacks_spec.rb
CHANGED
data/spec/conversion_spec.rb
CHANGED
@@ -40,7 +40,7 @@ describe 'Conversion' do
|
|
40
40
|
|
41
41
|
it "should work without arguments" do
|
42
42
|
post = build_post_with_comment
|
43
|
-
post.
|
43
|
+
post.to_rson.should == {
|
44
44
|
text: 'StarCraft releasing soon!',
|
45
45
|
token: 'secret',
|
46
46
|
comments: [
|
@@ -51,14 +51,14 @@ describe 'Conversion' do
|
|
51
51
|
|
52
52
|
it "should accept :only, :except and :methods options" do
|
53
53
|
post = build_post_with_comment
|
54
|
-
post.
|
55
|
-
post.
|
54
|
+
post.to_rson(only: :text).should == {text: 'StarCraft releasing soon!'}
|
55
|
+
post.to_rson(except: :token).should == {
|
56
56
|
text: 'StarCraft releasing soon!',
|
57
57
|
comments: [
|
58
58
|
{text: 'Cool!'}
|
59
59
|
]
|
60
60
|
}
|
61
|
-
post.
|
61
|
+
post.to_rson(only: [], methods: :teaser).should == {teaser: 'StarCraft r'}
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should use conversion profiles" do
|
@@ -68,13 +68,21 @@ describe 'Conversion' do
|
|
68
68
|
|
69
69
|
post = build_post_with_comment
|
70
70
|
|
71
|
-
-> {post.
|
71
|
+
-> {post.to_rson(profile: :public)}.should raise_error(/profile :public not defined for Comment/)
|
72
72
|
|
73
73
|
Comment.class_eval do
|
74
74
|
profile :public
|
75
75
|
end
|
76
76
|
|
77
|
-
post.
|
77
|
+
post.to_rson(profile: :public).should == {
|
78
|
+
text: 'StarCraft releasing soon!',
|
79
|
+
teaser: 'StarCraft r',
|
80
|
+
comments: [
|
81
|
+
{text: 'Cool!'}
|
82
|
+
]
|
83
|
+
}
|
84
|
+
|
85
|
+
post.to_rson(:public).should == {
|
78
86
|
text: 'StarCraft releasing soon!',
|
79
87
|
teaser: 'StarCraft r',
|
80
88
|
comments: [
|
@@ -91,29 +99,29 @@ describe 'Conversion' do
|
|
91
99
|
post = Post.new text: 'StarCraft releasing soon!'
|
92
100
|
post.valid?.should be_false
|
93
101
|
|
94
|
-
post.
|
102
|
+
post.to_rson.should == {
|
95
103
|
text: 'StarCraft releasing soon!',
|
96
104
|
errors: {token: ["can't be empty"]}
|
97
105
|
}
|
98
106
|
|
99
|
-
post.
|
107
|
+
post.to_rson(errors: false).should == {
|
100
108
|
text: 'StarCraft releasing soon!'
|
101
109
|
}
|
102
110
|
end
|
103
111
|
|
104
112
|
it "should convert to to_json" do
|
105
113
|
post = build_post_with_comment
|
106
|
-
|
107
|
-
|
108
|
-
post.should_receive(:
|
114
|
+
hash = mock
|
115
|
+
hash.should_receive(:to_json).and_return(:ok)
|
116
|
+
post.should_receive(:to_rson).with(only: :text).and_return(hash)
|
109
117
|
post.to_json(only: :text).should == :ok
|
110
118
|
end
|
111
119
|
|
112
120
|
it "should convert to to_xml" do
|
113
121
|
post = build_post_with_comment
|
114
|
-
|
115
|
-
|
116
|
-
post.should_receive(:
|
122
|
+
hash = mock
|
123
|
+
hash.should_receive(:to_xml).and_return(:ok)
|
124
|
+
post.should_receive(:to_rson).with(only: :text).and_return(hash)
|
117
125
|
post.to_xml(only: :text).should == :ok
|
118
126
|
end
|
119
127
|
end
|
data/spec/crud_spec.rb
CHANGED
@@ -20,6 +20,25 @@ describe "Model CRUD" do
|
|
20
20
|
end
|
21
21
|
after{remove_constants :Unit}
|
22
22
|
|
23
|
+
it 'save should return true or false' do
|
24
|
+
# Successfull create and update.
|
25
|
+
unit = Unit.new
|
26
|
+
unit.save.class.should == TrueClass
|
27
|
+
unit.name = 'Another'
|
28
|
+
unit.save.class.should == TrueClass
|
29
|
+
|
30
|
+
# Invalid create.
|
31
|
+
unit = Unit.new
|
32
|
+
unit.stub!(:valid?).and_return false
|
33
|
+
unit.save.class.should == FalseClass
|
34
|
+
|
35
|
+
# Invalid update.
|
36
|
+
unit = Unit.new
|
37
|
+
unit.save.should be_true
|
38
|
+
unit.stub!(:valid?).and_return false
|
39
|
+
unit.save.class.should == FalseClass
|
40
|
+
end
|
41
|
+
|
23
42
|
it 'should perform CRUD' do
|
24
43
|
# Read.
|
25
44
|
Unit.count.should == 0
|
@@ -77,10 +96,7 @@ describe "Model CRUD" do
|
|
77
96
|
|
78
97
|
it 'should create model' do
|
79
98
|
u = Unit.create(name: 'Zeratul')
|
80
|
-
u.
|
81
|
-
|
82
|
-
u = Unit.create!(name: 'Zeratul')
|
83
|
-
u.new_record?.should be_false
|
99
|
+
u.new?.should be_false
|
84
100
|
end
|
85
101
|
|
86
102
|
it 'should delete all models' do
|
data/spec/misc_spec.rb
CHANGED
@@ -11,10 +11,10 @@ describe 'Miscellaneous' do
|
|
11
11
|
attr_accessor :name
|
12
12
|
end
|
13
13
|
end
|
14
|
-
after{remove_constants :
|
14
|
+
after{remove_constants :Unit, :User}
|
15
15
|
|
16
16
|
it "should create timestamps" do
|
17
|
-
class
|
17
|
+
class Unit
|
18
18
|
inherit Mongo::Model
|
19
19
|
collection :units
|
20
20
|
|
@@ -23,10 +23,10 @@ describe 'Miscellaneous' do
|
|
23
23
|
timestamps!
|
24
24
|
end
|
25
25
|
|
26
|
-
unit =
|
26
|
+
unit = Unit.build name: 'Zeratul'
|
27
27
|
unit.save!
|
28
28
|
|
29
|
-
unit =
|
29
|
+
unit = Unit.first
|
30
30
|
unit.created_at.should_not be_nil
|
31
31
|
unit.updated_at.should_not be_nil
|
32
32
|
created_at,updated_at = unit.created_at, unit.updated_at
|
@@ -37,10 +37,10 @@ describe 'Miscellaneous' do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'should have cache' do
|
40
|
-
class
|
40
|
+
class Unit
|
41
41
|
inherit Mongo::Model
|
42
42
|
end
|
43
|
-
u =
|
43
|
+
u = Unit.new
|
44
44
|
u._cache.should == {}
|
45
45
|
end
|
46
46
|
|
@@ -64,4 +64,45 @@ describe 'Miscellaneous' do
|
|
64
64
|
u.reload
|
65
65
|
u.name.should == 'Zeratul'
|
66
66
|
end
|
67
|
+
|
68
|
+
describe 'original' do
|
69
|
+
before do
|
70
|
+
class Unit
|
71
|
+
inherit Mongo::Model
|
72
|
+
collection :units
|
73
|
+
|
74
|
+
attr_accessor :name
|
75
|
+
end
|
76
|
+
|
77
|
+
@unit = Unit.new.tap{|u| u.name = "Zeratul"}
|
78
|
+
end
|
79
|
+
after{remove_constants :Unit}
|
80
|
+
|
81
|
+
it "should query original from database" do
|
82
|
+
@unit.original.should be_nil
|
83
|
+
@unit.save!
|
84
|
+
|
85
|
+
unit = Unit.first
|
86
|
+
unit.name = "Tassadar"
|
87
|
+
|
88
|
+
Unit.should_receive(:first).with(_id: unit._id).and_return{db.units.first(_id: unit._id)}
|
89
|
+
unit.original.name.should == "Zeratul"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should use identity map if provided" do
|
93
|
+
Unit.inherit Mongo::Model::IdentityMap
|
94
|
+
|
95
|
+
@unit.original.should be_nil
|
96
|
+
@unit.save!
|
97
|
+
|
98
|
+
Unit.identity_map.size.should == 0
|
99
|
+
unit = Unit.first
|
100
|
+
Unit.identity_map.size.should == 1
|
101
|
+
|
102
|
+
unit.name = "Tassadar"
|
103
|
+
|
104
|
+
Unit.should_not_receive :first
|
105
|
+
unit.original.name.should == "Zeratul"
|
106
|
+
end
|
107
|
+
end
|
67
108
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -74,7 +74,9 @@ describe "Query" do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
|
77
|
+
u = SpecialUnit.query(name: 'Zeratul').build status: 'active'
|
78
|
+
u.status.should be_nil
|
79
|
+
|
78
80
|
u = SpecialUnit.query(name: 'Zeratul', status: 'active').build age: 500
|
79
81
|
u.status.should == 'active'
|
80
82
|
end
|
data/spec/validation_spec.rb
CHANGED
@@ -142,4 +142,26 @@ describe "Validation" do
|
|
142
142
|
unit.should be_valid
|
143
143
|
end
|
144
144
|
end
|
145
|
+
|
146
|
+
context "database exceptions" do
|
147
|
+
before do
|
148
|
+
class Unit
|
149
|
+
inherit Mongo::Model
|
150
|
+
collection :units
|
151
|
+
|
152
|
+
attr_accessor :name
|
153
|
+
end
|
154
|
+
end
|
155
|
+
after{remove_constants :Unit}
|
156
|
+
|
157
|
+
it "should convert unique index exception to errors" do
|
158
|
+
db.units.create_index [["name", 1]], unique: true
|
159
|
+
|
160
|
+
Unit.create name: 'Zeratul'
|
161
|
+
|
162
|
+
unit = Unit.new name: 'Zeratul'
|
163
|
+
unit.save.should be_false
|
164
|
+
unit.errors[:base].should == ["not unique value!"]
|
165
|
+
end
|
166
|
+
end
|
145
167
|
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: 2.0
|
4
|
+
version: 2.1.0
|
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: 2011-
|
12
|
+
date: 2011-12-19 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongodb
|
16
|
-
requirement: &
|
16
|
+
requirement: &70169713604240 !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: *70169713604240
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: validatable2
|
27
|
-
requirement: &
|
27
|
+
requirement: &70169713603760 !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: *70169713603760
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: ruby_ext
|
38
|
-
requirement: &
|
38
|
+
requirement: &70169713603260 !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: *70169713603260
|
47
47
|
description:
|
48
48
|
email:
|
49
49
|
executables: []
|
@@ -58,7 +58,10 @@ files:
|
|
58
58
|
- lib/mongo/model/conversion.rb
|
59
59
|
- lib/mongo/model/crud.rb
|
60
60
|
- lib/mongo/model/db.rb
|
61
|
+
- lib/mongo/model/identity_map.rb
|
61
62
|
- lib/mongo/model/integration/file_model.rb
|
63
|
+
- lib/mongo/model/integration/rad/tasks.rb
|
64
|
+
- lib/mongo/model/integration/rad.rb
|
62
65
|
- lib/mongo/model/integration/rails.rb
|
63
66
|
- lib/mongo/model/integration/validatable/uniqueness_validator.rb
|
64
67
|
- lib/mongo/model/integration/validatable.rb
|
@@ -70,7 +73,7 @@ files:
|
|
70
73
|
- lib/mongo/model/scope.rb
|
71
74
|
- lib/mongo/model/spec.rb
|
72
75
|
- lib/mongo/model/support/conversions.rb
|
73
|
-
- lib/mongo/model/support.rb
|
76
|
+
- lib/mongo/model/support/rson.rb
|
74
77
|
- lib/mongo/model/validation.rb
|
75
78
|
- lib/mongo/model.rb
|
76
79
|
- lib/mongodb_model/gems.rb
|
@@ -109,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
112
|
version: '0'
|
110
113
|
requirements: []
|
111
114
|
rubyforge_project:
|
112
|
-
rubygems_version: 1.8.
|
115
|
+
rubygems_version: 1.8.10
|
113
116
|
signing_key:
|
114
117
|
specification_version: 3
|
115
118
|
summary: Object Model for MongoDB
|
data/lib/mongo/model/support.rb
DELETED