mongomatic 0.5.8 → 0.6.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/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
|