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 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 << ["Name", "can't be empty"] if self["name"].blank?
20
- self.errors << ["Email", "can't be empty"] if self["email"].blank?
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 << ["name", "blank"] if self["name"].blank?
89
- self.errors << ["email", "blank"] if self["email"].blank?
90
- self.errors << ["address.zip", "blank"] if (self["address"] || {})["zip"].blank?
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 self['name'], "Name cannot be blank"
118
- not_be_match self['nickname'], "Nickname cannot contain an uppercase letter", :with => /[A-Z]/
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
@@ -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
- begin
76
- send(meth)
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 << ["name", "cannot be blank"]
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
- begin
258
- send(meth)
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
@@ -1,22 +1,83 @@
1
1
  module Mongomatic
2
- class Errors < Array
3
- def full_messages(sep=" ")
4
- collect { |e| e.join(sep) }
2
+ class Errors
3
+ def initialize
4
+ @errors = HashWithIndifferentAccess.new
5
5
  end
6
6
 
7
- def on(field, sep=" ")
8
- ret = []
9
- self.each do |err|
10
- ret << err.join(sep) if err.first =~ /^#{field.to_s.split('_').join(' ')}/i
11
- end
12
- case ret.size
13
- when 0
14
- nil
15
- when 1
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
- ret
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
@@ -80,7 +80,12 @@ module Mongomatic
80
80
  end
81
81
 
82
82
  def add_error_msg
83
- instance.errors << Array(message)
83
+ vars = Array(message)
84
+ if vars.size == 2
85
+ instance.errors.add(vars[0], vars[1])
86
+ else
87
+ instance.errors.add_to_base(vars[0])
88
+ end
84
89
  end
85
90
  end
86
91
  end
data/lib/mongomatic.rb CHANGED
@@ -1,5 +1,5 @@
1
- gem "bson", "= 1.1"
2
- gem "mongo", "= 1.1"
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
@@ -31,7 +31,7 @@ class Person < Mongomatic::Base
31
31
  end
32
32
 
33
33
  def validate
34
- self.errors << ["Name", "can't be empty"] if self["name"].blank?
34
+ self.errors.add "name", "can't be empty" if self["name"].blank?
35
35
  end
36
36
 
37
37
  private
@@ -94,7 +94,7 @@ class TestMongomatic < Test::Unit::TestCase
94
94
  p = Person.new
95
95
 
96
96
  assert !p.valid?
97
- assert_equal(["Name can't be empty"], p.errors.full_messages)
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 ['name cannot be empty', 'name must be at least 3 characters long'], p.errors.on(:name)
496
- assert_equal 'age must be a number', p.errors.on('age')
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 'name must be at least 3 characters long', p.errors.on('name')
503
- assert_nil p.errors.on(:age)
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
- assert_nil p.errors.on(:name)
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 must be a number'
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 ['name cannot be empty', 'name must be at least 3 characters long'], p.errors.on(:name)
525
- assert_equal 'age must be a number', p.errors.on('age')
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 'name must be at least 3 characters long', p.errors.on('name')
532
- assert_nil p.errors.on(:age)
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
- assert_nil p.errors.on(:name)
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'], ['Name', 'cannot be empty']
546
- be_expected self['age'], 'Age cannot be empty'
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 'Name cannot be empty', p.errors.on('name')
553
- assert_equal 'Age cannot be empty', p.errors.on(:age)
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'], 'Hair color must exist'
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 'Hair color must exist', p.errors.on(:hair_color)
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
- - 5
8
- - 8
9
- version: 0.5.8
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-13 00:00:00 -07:00
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