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 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