mongomatic 0.5.8 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +21 -7
- data/lib/mongomatic/active_model_compliancy.rb +29 -0
- data/lib/mongomatic/base.rb +6 -11
- data/lib/mongomatic/errors.rb +76 -15
- data/lib/mongomatic/expectations/be_reference.rb +15 -0
- data/lib/mongomatic/expectations.rb +6 -1
- data/lib/mongomatic.rb +3 -2
- data/test/helper.rb +1 -1
- data/test/test_mongomatic.rb +71 -20
- metadata +8 -6
data/README.rdoc
CHANGED
@@ -2,6 +2,20 @@
|
|
2
2
|
|
3
3
|
Mongomatic allows you to map your Ruby objects to Mongo documents. It is designed to be fast and simple.
|
4
4
|
|
5
|
+
== 0.6.0 CHANGELOG NOTES
|
6
|
+
|
7
|
+
!! THE ERROR CLASS HAS BEEN REWORKED IN THIS VERSION.
|
8
|
+
!! DO NOT EXPECT YOUR UPGRADE TO BE SEAMLESS. NOTHING /SHOULD/
|
9
|
+
!! BREAK BUT YOU SHOULD TEST THOROUGHLY.
|
10
|
+
|
11
|
+
* Added methods to bring ActiveModel compliancy
|
12
|
+
|
13
|
+
* Pulled in do_callback fix (no more NoMethodError catching)
|
14
|
+
|
15
|
+
* Relaxed restrictions on dependencies
|
16
|
+
|
17
|
+
* Reworked the Error class to mimic the ActiveModel style errors.
|
18
|
+
|
5
19
|
== What's different about Mongomatic?
|
6
20
|
|
7
21
|
* Follows Mongo idioms wherever possible.
|
@@ -16,8 +30,8 @@ Mongomatic allows you to map your Ruby objects to Mongo documents. It is designe
|
|
16
30
|
|
17
31
|
class User < Mongomatic::Base
|
18
32
|
def validate
|
19
|
-
self.errors
|
20
|
-
self.errors
|
33
|
+
self.errors.add "name", "can't be empty" if self["name"].blank?
|
34
|
+
self.errors.add "email", "can't be empty" if self["email"].blank?
|
21
35
|
end
|
22
36
|
end
|
23
37
|
|
@@ -85,9 +99,9 @@ You can add validations to your model by creating a validate method. If your val
|
|
85
99
|
|
86
100
|
class Person < Mongomatic::Base
|
87
101
|
def validate
|
88
|
-
self.errors
|
89
|
-
self.errors
|
90
|
-
self.errors
|
102
|
+
self.errors.add "name", "blank" if self["name"].blank?
|
103
|
+
self.errors.add "email", "blank" if self["email"].blank?
|
104
|
+
self.errors.add "address.zip", "blank" if (self["address"] || {})["zip"].blank?
|
91
105
|
end
|
92
106
|
end
|
93
107
|
|
@@ -114,8 +128,8 @@ To make writing your validate method a little simpler you can use Mongomatic::Ex
|
|
114
128
|
|
115
129
|
def validate
|
116
130
|
expectations do
|
117
|
-
be_present
|
118
|
-
not_be_match self['nickname'], "
|
131
|
+
be_present self['name'], ["name", "cannot be blank"]
|
132
|
+
not_be_match self['nickname'], ["nickname", "cannot contain an uppercase letter"], :with => /[A-Z]/
|
119
133
|
end
|
120
134
|
end
|
121
135
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mongomatic
|
2
|
+
module ActiveModelCompliancy
|
3
|
+
|
4
|
+
def to_model
|
5
|
+
self
|
6
|
+
end
|
7
|
+
|
8
|
+
def new_record?
|
9
|
+
new?
|
10
|
+
end
|
11
|
+
|
12
|
+
def destroyed?
|
13
|
+
removed?
|
14
|
+
end
|
15
|
+
|
16
|
+
def persisted?
|
17
|
+
!new?
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_key
|
21
|
+
self["_id"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_param
|
25
|
+
self["_id"] ? self["_id"].to_s : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/mongomatic/base.rb
CHANGED
@@ -2,6 +2,7 @@ module Mongomatic
|
|
2
2
|
class Base
|
3
3
|
include Mongomatic::Modifiers
|
4
4
|
include Mongomatic::Util
|
5
|
+
include Mongomatic::ActiveModelCompliancy
|
5
6
|
|
6
7
|
class << self
|
7
8
|
# Returns this models own db attribute if set, otherwise will return Mongomatic.db
|
@@ -72,11 +73,8 @@ module Mongomatic
|
|
72
73
|
private
|
73
74
|
|
74
75
|
def do_callback(meth)
|
75
|
-
|
76
|
-
|
77
|
-
rescue NoMethodError => e
|
78
|
-
false
|
79
|
-
end
|
76
|
+
return false unless respond_to?(meth, true)
|
77
|
+
send(meth)
|
80
78
|
end
|
81
79
|
end
|
82
80
|
|
@@ -102,7 +100,7 @@ module Mongomatic
|
|
102
100
|
# Simply push your errors into the self.errors property and
|
103
101
|
# if self.errors remains empty your document will be valid.
|
104
102
|
# def validate
|
105
|
-
# self.errors
|
103
|
+
# self.errors.add "name", "cannot be blank"
|
106
104
|
# end
|
107
105
|
def validate
|
108
106
|
true
|
@@ -254,11 +252,8 @@ module Mongomatic
|
|
254
252
|
end
|
255
253
|
|
256
254
|
def do_callback(meth)
|
257
|
-
|
258
|
-
|
259
|
-
rescue NoMethodError => e
|
260
|
-
false
|
261
|
-
end
|
255
|
+
return false unless respond_to?(meth, true)
|
256
|
+
send(meth)
|
262
257
|
end
|
263
258
|
end
|
264
259
|
end
|
data/lib/mongomatic/errors.rb
CHANGED
@@ -1,22 +1,83 @@
|
|
1
1
|
module Mongomatic
|
2
|
-
class Errors
|
3
|
-
def
|
4
|
-
|
2
|
+
class Errors
|
3
|
+
def initialize
|
4
|
+
@errors = HashWithIndifferentAccess.new
|
5
5
|
end
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
ret.first
|
7
|
+
def add(field, message)
|
8
|
+
@errors[field] ||= []
|
9
|
+
@errors[field] << message
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(error_array)
|
13
|
+
error_array = Array(error_array)
|
14
|
+
if error_array.size == 2
|
15
|
+
add error_array[0], error_array[1]
|
17
16
|
else
|
18
|
-
|
17
|
+
add_to_base error_array[0]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_to_base(message)
|
22
|
+
@errors["base"] ||= []
|
23
|
+
@errors["base"] << message
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove(field, message)
|
27
|
+
@errors[field] ||= []
|
28
|
+
@errors[field].delete message
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty?
|
32
|
+
!(@errors.any? { |k,v| v && !v.empty? })
|
33
|
+
end
|
34
|
+
|
35
|
+
def full_messages
|
36
|
+
full_messages = []
|
37
|
+
@errors.each do |field, messages|
|
38
|
+
messages.each do |message|
|
39
|
+
msg = []
|
40
|
+
msg << field unless field == "base"
|
41
|
+
msg << message
|
42
|
+
full_messages << msg.join(" ")
|
43
|
+
end
|
19
44
|
end
|
45
|
+
full_messages
|
46
|
+
end
|
47
|
+
|
48
|
+
def [](field)
|
49
|
+
@errors[field] || []
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_hash
|
53
|
+
@errors
|
54
|
+
end
|
55
|
+
|
56
|
+
def on(field)
|
57
|
+
self[field]
|
20
58
|
end
|
21
59
|
end
|
22
|
-
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# module Mongomatic
|
63
|
+
# class Errors < Array
|
64
|
+
# def full_messages(sep=" ")
|
65
|
+
# collect { |e| e.join(sep) }
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# def on(field, sep=" ")
|
69
|
+
# ret = []
|
70
|
+
# self.each do |err|
|
71
|
+
# ret << err.join(sep) if err.first =~ /^#{field.to_s.split('_').join(' ')}/i
|
72
|
+
# end
|
73
|
+
# case ret.size
|
74
|
+
# when 0
|
75
|
+
# nil
|
76
|
+
# when 1
|
77
|
+
# ret.first
|
78
|
+
# else
|
79
|
+
# ret
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
# end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Mongomatic
|
2
|
+
module Expectations
|
3
|
+
class BeReference < Expectation
|
4
|
+
def self.name
|
5
|
+
"reference"
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_be
|
9
|
+
return true if opts[:allow_nil] && value.nil?
|
10
|
+
|
11
|
+
add_error_msg unless value.is_a? BSON::ObjectId
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/mongomatic.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
gem "bson", "
|
2
|
-
gem "mongo", "
|
1
|
+
gem "bson", "~> 1.1"
|
2
|
+
gem "mongo", "~> 1.1"
|
3
3
|
gem "activesupport", ">= 2.3.5"
|
4
4
|
|
5
5
|
require "bson"
|
@@ -35,4 +35,5 @@ require "#{File.dirname(__FILE__)}/mongomatic/cursor"
|
|
35
35
|
require "#{File.dirname(__FILE__)}/mongomatic/modifiers"
|
36
36
|
require "#{File.dirname(__FILE__)}/mongomatic/errors"
|
37
37
|
require "#{File.dirname(__FILE__)}/mongomatic/expectations"
|
38
|
+
require "#{File.dirname(__FILE__)}/mongomatic/active_model_compliancy"
|
38
39
|
require "#{File.dirname(__FILE__)}/mongomatic/base"
|
data/test/helper.rb
CHANGED
data/test/test_mongomatic.rb
CHANGED
@@ -94,7 +94,7 @@ class TestMongomatic < Test::Unit::TestCase
|
|
94
94
|
p = Person.new
|
95
95
|
|
96
96
|
assert !p.valid?
|
97
|
-
assert_equal(["
|
97
|
+
assert_equal(["name can't be empty"], p.errors.full_messages)
|
98
98
|
|
99
99
|
p["name"] = "Ben Myles"
|
100
100
|
p["birth_year"] = 1984
|
@@ -248,6 +248,23 @@ class TestMongomatic < Test::Unit::TestCase
|
|
248
248
|
assert_equal found["_id"], "mycustomid"
|
249
249
|
assert_equal 26, found["age"]
|
250
250
|
end
|
251
|
+
|
252
|
+
should "be able to use array style error adding" do
|
253
|
+
class Foobar < Mongomatic::Base
|
254
|
+
def validate
|
255
|
+
errors << ["color", "must not be blank"] if self["color"].blank?
|
256
|
+
errors << "missing style" if self["style"].blank?
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
f = Foobar.new
|
261
|
+
assert !f.valid?
|
262
|
+
assert_equal ["color must not be blank", "missing style"], f.errors.full_messages
|
263
|
+
f["color"] = "pink"; f.valid?
|
264
|
+
assert_equal ["missing style"], f.errors.full_messages
|
265
|
+
f["style"] = "awesome"; f.valid?
|
266
|
+
assert_equal [], f.errors.full_messages
|
267
|
+
end
|
251
268
|
|
252
269
|
should "be able to use the be_expect expectation" do
|
253
270
|
p = Person.new
|
@@ -444,6 +461,25 @@ class TestMongomatic < Test::Unit::TestCase
|
|
444
461
|
assert p.valid?
|
445
462
|
end
|
446
463
|
|
464
|
+
should "be able to use be_reference expectation" do
|
465
|
+
id = Person.new('name' => 'jordan').insert
|
466
|
+
p = Person.new
|
467
|
+
class << p
|
468
|
+
def validate
|
469
|
+
expectations do
|
470
|
+
be_reference self['friend'], 'friend must be an ObjectId'
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
assert !p.valid?
|
476
|
+
assert_equal ["friend must be an ObjectId"], p.errors.full_messages
|
477
|
+
|
478
|
+
p['friend'] = id
|
479
|
+
|
480
|
+
assert p.valid?
|
481
|
+
end
|
482
|
+
|
447
483
|
should "raise an error if expectations are called outside of helper block" do
|
448
484
|
p = Person.new
|
449
485
|
class << p
|
@@ -492,20 +528,20 @@ class TestMongomatic < Test::Unit::TestCase
|
|
492
528
|
end
|
493
529
|
|
494
530
|
p.valid?
|
495
|
-
assert_equal ['
|
496
|
-
assert_equal '
|
531
|
+
assert_equal ['cannot be empty', 'must be at least 3 characters long'], p.errors.on(:name)
|
532
|
+
assert_equal ['must be a number'], p.errors.on('age')
|
497
533
|
|
498
534
|
p['name'] = 'Jo'
|
499
535
|
p['age'] = 21
|
500
536
|
|
501
537
|
p.valid?
|
502
|
-
assert_equal '
|
503
|
-
|
538
|
+
assert_equal ['must be at least 3 characters long'], p.errors.on('name')
|
539
|
+
assert_equal [], p.errors.on(:age)
|
504
540
|
|
505
541
|
p['name'] = 'Jordan'
|
506
542
|
|
507
543
|
p.valid?
|
508
|
-
|
544
|
+
assert_equal [], p.errors.on(:name)
|
509
545
|
end
|
510
546
|
|
511
547
|
should "be able to use errors.on with one part error messages" do
|
@@ -513,28 +549,28 @@ class TestMongomatic < Test::Unit::TestCase
|
|
513
549
|
class << p
|
514
550
|
def validate
|
515
551
|
expectations do
|
516
|
-
be_expected self['name'], 'name cannot be empty'
|
517
|
-
be_of_length self['name'], 'name must be at least 3 characters long', :minimum => 3
|
518
|
-
be_a_number self['age'], 'age
|
552
|
+
be_expected self['name'], ['name', 'cannot be empty' ]
|
553
|
+
be_of_length self['name'], ['name', 'must be at least 3 characters long'], :minimum => 3
|
554
|
+
be_a_number self['age'], ['age','must be a number']
|
519
555
|
end
|
520
556
|
end
|
521
557
|
end
|
522
558
|
|
523
559
|
p.valid?
|
524
|
-
assert_equal ['
|
525
|
-
assert_equal '
|
560
|
+
assert_equal ['cannot be empty', 'must be at least 3 characters long'], p.errors.on(:name)
|
561
|
+
assert_equal ['must be a number'], p.errors.on('age')
|
526
562
|
|
527
563
|
p['name'] = 'Jo'
|
528
564
|
p['age'] = 21
|
529
565
|
|
530
566
|
p.valid?
|
531
|
-
assert_equal '
|
532
|
-
|
567
|
+
assert_equal ['must be at least 3 characters long'], p.errors.on('name')
|
568
|
+
assert_equal [], p.errors.on(:age)
|
533
569
|
|
534
570
|
p['name'] = 'Jordan'
|
535
571
|
|
536
572
|
p.valid?
|
537
|
-
|
573
|
+
assert_equal [], p.errors.on(:name)
|
538
574
|
end
|
539
575
|
|
540
576
|
should "be able to use errors.on case insensitive" do
|
@@ -542,15 +578,15 @@ class TestMongomatic < Test::Unit::TestCase
|
|
542
578
|
class << p
|
543
579
|
def validate
|
544
580
|
expectations do
|
545
|
-
be_expected self['name'], ['
|
546
|
-
be_expected self['age'], '
|
581
|
+
be_expected self['name'], ['name', 'cannot be empty']
|
582
|
+
be_expected self['age'], ['age','cannot be empty']
|
547
583
|
end
|
548
584
|
end
|
549
585
|
end
|
550
586
|
|
551
587
|
p.valid?
|
552
|
-
assert_equal '
|
553
|
-
assert_equal '
|
588
|
+
assert_equal ['cannot be empty'], p.errors.on('name')
|
589
|
+
assert_equal ['cannot be empty'], p.errors.on(:age)
|
554
590
|
end
|
555
591
|
|
556
592
|
should "be able to use errors.on with multi word fields" do
|
@@ -558,13 +594,13 @@ class TestMongomatic < Test::Unit::TestCase
|
|
558
594
|
class << p
|
559
595
|
def validate
|
560
596
|
expectations do
|
561
|
-
be_expected self['hair_color'], '
|
597
|
+
be_expected self['hair_color'], ['hair_color', 'must exist']
|
562
598
|
end
|
563
599
|
end
|
564
600
|
end
|
565
601
|
|
566
602
|
p.valid?
|
567
|
-
assert_equal '
|
603
|
+
assert_equal ['must exist'], p.errors.on(:hair_color)
|
568
604
|
end
|
569
605
|
|
570
606
|
should "be able to use has_key?" do
|
@@ -602,4 +638,19 @@ class TestMongomatic < Test::Unit::TestCase
|
|
602
638
|
assert_equal "Meta+Level Games", p.value_for_key("employer.name")
|
603
639
|
assert_nil p.value_for_key("some_key.that_does_not.exist")
|
604
640
|
end
|
641
|
+
|
642
|
+
should "not rescue a NoMethodError raised in a callback" do
|
643
|
+
class Thing < Mongomatic::Base
|
644
|
+
def before_insert
|
645
|
+
raise NoMethodError
|
646
|
+
end
|
647
|
+
|
648
|
+
def self.before_drop
|
649
|
+
raise NoMethodError
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
assert_raise(NoMethodError) { Thing.new.insert }
|
654
|
+
assert_raise(NoMethodError) { Thing.drop }
|
655
|
+
end
|
605
656
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ben Myles
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10
|
17
|
+
date: 2010-11-10 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
|
-
- -
|
41
|
+
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
segments:
|
44
44
|
- 1
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
|
-
- -
|
55
|
+
- - ~>
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
segments:
|
58
58
|
- 1
|
@@ -86,10 +86,12 @@ extra_rdoc_files:
|
|
86
86
|
- README.rdoc
|
87
87
|
files:
|
88
88
|
- lib/mongomatic.rb
|
89
|
+
- lib/mongomatic/active_model_compliancy.rb
|
89
90
|
- lib/mongomatic/base.rb
|
90
91
|
- lib/mongomatic/cursor.rb
|
91
92
|
- lib/mongomatic/errors.rb
|
92
93
|
- lib/mongomatic/expectations.rb
|
94
|
+
- lib/mongomatic/expectations/be_reference.rb
|
93
95
|
- lib/mongomatic/expectations/expected.rb
|
94
96
|
- lib/mongomatic/expectations/is_number.rb
|
95
97
|
- lib/mongomatic/expectations/match.rb
|