ramsingla-mongomapper 0.2.1

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.
Files changed (42) hide show
  1. data/.gitignore +7 -0
  2. data/History +30 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/Rakefile +71 -0
  6. data/VERSION +1 -0
  7. data/lib/mongomapper.rb +60 -0
  8. data/lib/mongomapper/associations.rb +69 -0
  9. data/lib/mongomapper/associations/array_proxy.rb +6 -0
  10. data/lib/mongomapper/associations/base.rb +50 -0
  11. data/lib/mongomapper/associations/belongs_to_proxy.rb +26 -0
  12. data/lib/mongomapper/associations/has_many_embedded_proxy.rb +19 -0
  13. data/lib/mongomapper/associations/has_many_proxy.rb +28 -0
  14. data/lib/mongomapper/associations/polymorphic_belongs_to_proxy.rb +31 -0
  15. data/lib/mongomapper/associations/proxy.rb +60 -0
  16. data/lib/mongomapper/callbacks.rb +106 -0
  17. data/lib/mongomapper/document.rb +263 -0
  18. data/lib/mongomapper/embedded_document.rb +295 -0
  19. data/lib/mongomapper/finder_options.rb +81 -0
  20. data/lib/mongomapper/key.rb +82 -0
  21. data/lib/mongomapper/observing.rb +50 -0
  22. data/lib/mongomapper/pagination.rb +52 -0
  23. data/lib/mongomapper/rails_compatibility.rb +23 -0
  24. data/lib/mongomapper/save_with_validation.rb +19 -0
  25. data/lib/mongomapper/serialization.rb +55 -0
  26. data/lib/mongomapper/serializers/json_serializer.rb +77 -0
  27. data/lib/mongomapper/validations.rb +47 -0
  28. data/mongomapper.gemspec +105 -0
  29. data/test/serializers/test_json_serializer.rb +104 -0
  30. data/test/test_associations.rb +211 -0
  31. data/test/test_callbacks.rb +84 -0
  32. data/test/test_document.rb +995 -0
  33. data/test/test_embedded_document.rb +253 -0
  34. data/test/test_finder_options.rb +148 -0
  35. data/test/test_helper.rb +62 -0
  36. data/test/test_key.rb +200 -0
  37. data/test/test_mongomapper.rb +28 -0
  38. data/test/test_observing.rb +101 -0
  39. data/test/test_rails_compatibility.rb +29 -0
  40. data/test/test_serializations.rb +54 -0
  41. data/test/test_validations.rb +409 -0
  42. metadata +156 -0
@@ -0,0 +1,47 @@
1
+ module MongoMapper
2
+ module Validations
3
+ class ValidatesUniquenessOf < Validatable::ValidationBase
4
+ def valid?(instance)
5
+ # TODO: scope
6
+ doc = instance._root.class.find(:first, :conditions => { instance.full_key_path(self.attribute) => instance[attribute]}, :limit => 1)
7
+ doc.nil? || instance._root.id == doc.id
8
+ end
9
+
10
+ def message(instance)
11
+ super || "has already been taken"
12
+ end
13
+ end
14
+
15
+ class ValidatesExclusionOf < Validatable::ValidationBase
16
+ required_option :within
17
+
18
+ def valid?(instance)
19
+ value = instance[attribute]
20
+ return true if allow_nil && value.nil?
21
+ return true if allow_blank && value.blank?
22
+
23
+ !within.include?(instance[attribute])
24
+ end
25
+
26
+ def message(instance)
27
+ super || "is reserved"
28
+ end
29
+ end
30
+
31
+ class ValidatesInclusionOf < Validatable::ValidationBase
32
+ required_option :within
33
+
34
+ def valid?(instance)
35
+ value = instance[attribute]
36
+ return true if allow_nil && value.nil?
37
+ return true if allow_blank && value.blank?
38
+
39
+ within.include?(value)
40
+ end
41
+
42
+ def message(instance)
43
+ super || "is not in the list"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,105 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{mongomapper}
5
+ s.version = "0.2.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["John Nunemaker", "Ram Singla"]
9
+ s.date = %q{2009-07-23}
10
+ s.email = %q{ram.singla@gmail.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "History",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "lib/mongomapper.rb",
23
+ "lib/mongomapper/associations.rb",
24
+ "lib/mongomapper/associations/array_proxy.rb",
25
+ "lib/mongomapper/associations/base.rb",
26
+ "lib/mongomapper/associations/belongs_to_proxy.rb",
27
+ "lib/mongomapper/associations/has_many_embedded_proxy.rb",
28
+ "lib/mongomapper/associations/has_many_proxy.rb",
29
+ "lib/mongomapper/associations/polymorphic_belongs_to_proxy.rb",
30
+ "lib/mongomapper/associations/proxy.rb",
31
+ "lib/mongomapper/callbacks.rb",
32
+ "lib/mongomapper/document.rb",
33
+ "lib/mongomapper/embedded_document.rb",
34
+ "lib/mongomapper/finder_options.rb",
35
+ "lib/mongomapper/key.rb",
36
+ "lib/mongomapper/observing.rb",
37
+ "lib/mongomapper/pagination.rb",
38
+ "lib/mongomapper/rails_compatibility.rb",
39
+ "lib/mongomapper/save_with_validation.rb",
40
+ "lib/mongomapper/serialization.rb",
41
+ "lib/mongomapper/serializers/json_serializer.rb",
42
+ "lib/mongomapper/validations.rb",
43
+ "mongomapper.gemspec",
44
+ "test/serializers/test_json_serializer.rb",
45
+ "test/test_associations.rb",
46
+ "test/test_callbacks.rb",
47
+ "test/test_document.rb",
48
+ "test/test_embedded_document.rb",
49
+ "test/test_finder_options.rb",
50
+ "test/test_helper.rb",
51
+ "test/test_key.rb",
52
+ "test/test_mongomapper.rb",
53
+ "test/test_observing.rb",
54
+ "test/test_rails_compatibility.rb",
55
+ "test/test_serializations.rb",
56
+ "test/test_validations.rb"
57
+ ]
58
+ s.has_rdoc = true
59
+ s.homepage = %q{http://github.com/jnunemaker/mongomapper}
60
+ s.rdoc_options = ["--charset=UTF-8"]
61
+ s.require_paths = ["lib"]
62
+ s.rubyforge_project = %q{mongomapper}
63
+ s.rubygems_version = %q{1.3.1}
64
+ s.summary = %q{Awesome gem for modeling your domain and storing it in mongo}
65
+ s.test_files = [
66
+ "test/serializers/test_json_serializer.rb",
67
+ "test/test_associations.rb",
68
+ "test/test_callbacks.rb",
69
+ "test/test_document.rb",
70
+ "test/test_embedded_document.rb",
71
+ "test/test_finder_options.rb",
72
+ "test/test_helper.rb",
73
+ "test/test_key.rb",
74
+ "test/test_mongomapper.rb",
75
+ "test/test_observing.rb",
76
+ "test/test_rails_compatibility.rb",
77
+ "test/test_serializations.rb",
78
+ "test/test_validations.rb"
79
+ ]
80
+
81
+ if s.respond_to? :specification_version then
82
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
83
+ s.specification_version = 2
84
+
85
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
86
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
87
+ s.add_runtime_dependency(%q<mongodb-mongo>, ["= 0.9"])
88
+ s.add_runtime_dependency(%q<jnunemaker-validatable>, ["= 1.7.1"])
89
+ s.add_development_dependency(%q<mocha>, ["= 0.9.4"])
90
+ s.add_development_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
91
+ else
92
+ s.add_dependency(%q<activesupport>, [">= 0"])
93
+ s.add_dependency(%q<mongodb-mongo>, ["= 0.9"])
94
+ s.add_dependency(%q<jnunemaker-validatable>, ["= 1.7.1"])
95
+ s.add_dependency(%q<mocha>, ["= 0.9.4"])
96
+ s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
97
+ end
98
+ else
99
+ s.add_dependency(%q<activesupport>, [">= 0"])
100
+ s.add_dependency(%q<mongodb-mongo>, ["= 0.9"])
101
+ s.add_dependency(%q<jnunemaker-validatable>, ["= 1.7.1"])
102
+ s.add_dependency(%q<mocha>, ["= 0.9.4"])
103
+ s.add_dependency(%q<jnunemaker-matchy>, ["= 0.4.0"])
104
+ end
105
+ end
@@ -0,0 +1,104 @@
1
+ require 'test_helper'
2
+
3
+ class JsonSerializationTest < Test::Unit::TestCase
4
+ class Contact
5
+ include MongoMapper::EmbeddedDocument
6
+ key :name, String
7
+ key :age, Integer
8
+ key :created_at, Time
9
+ key :awesome, Boolean
10
+ key :preferences, Hash
11
+ end
12
+
13
+ def setup
14
+ Contact.include_root_in_json = false
15
+ @contact = Contact.new(
16
+ :name => 'Konata Izumi',
17
+ :age => 16,
18
+ :created_at => Time.utc(2006, 8, 1),
19
+ :awesome => true,
20
+ :preferences => { :shows => 'anime' }
21
+ )
22
+ end
23
+
24
+ should "include demodulized root" do
25
+ Contact.include_root_in_json = true
26
+ assert_match %r{^\{"contact": \{}, @contact.to_json
27
+ end
28
+
29
+ should "encode all encodable attributes" do
30
+ json = @contact.to_json
31
+
32
+ assert_match %r{"name": "Konata Izumi"}, json
33
+ assert_match %r{"age": 16}, json
34
+ assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
35
+ assert_match %r{"awesome": true}, json
36
+ assert_match %r{"preferences": \{"shows": "anime"\}}, json
37
+ end
38
+
39
+ should "allow attribute filtering with only" do
40
+ json = @contact.to_json(:only => [:name, :age])
41
+
42
+ assert_match %r{"name": "Konata Izumi"}, json
43
+ assert_match %r{"age": 16}, json
44
+ assert_no_match %r{"awesome"}, json
45
+ assert_no_match %r{"created_at"}, json
46
+ assert_no_match %r{"preferences"}, json
47
+ end
48
+
49
+ should "allow attribute filtering with except" do
50
+ json = @contact.to_json(:except => [:name, :age])
51
+
52
+ assert_no_match %r{"name"}, json
53
+ assert_no_match %r{"age"}, json
54
+ assert_match %r{"awesome"}, json
55
+ assert_match %r{"created_at"}, json
56
+ assert_match %r{"preferences"}, json
57
+ end
58
+
59
+ context "including methods" do
60
+ setup do
61
+ def @contact.label; "Has cheezburger"; end
62
+ def @contact.favorite_quote; "Constraints are liberating"; end
63
+ end
64
+
65
+ should "include single method" do
66
+ # Single method.
67
+ assert_match %r{"label": "Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
68
+ end
69
+
70
+ should "include multiple methods" do
71
+ json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
72
+ assert_match %r{"label": "Has cheezburger"}, json
73
+ assert_match %r{"favorite_quote": "Constraints are liberating"}, json
74
+ end
75
+ end
76
+
77
+ context "array of records" do
78
+ setup do
79
+ @contacts = [
80
+ Contact.new(:name => 'David', :age => 39),
81
+ Contact.new(:name => 'Mary', :age => 14)
82
+ ]
83
+ end
84
+
85
+ should "allow attribute filtering with only" do
86
+ assert_equal %([{"name": "David"}, {"name": "Mary"}]), @contacts.to_json(:only => :name)
87
+ end
88
+
89
+ should "allow attribute filtering with except" do
90
+ json = @contacts.to_json(:except => [:name, :preferences, :awesome, :created_at])
91
+ assert_equal %([{"age": 39}, {"age": 14}]), json
92
+ end
93
+ end
94
+
95
+ should "allow options for hash of records" do
96
+ contacts = {
97
+ 1 => Contact.new(:name => 'David', :age => 39),
98
+ 2 => Contact.new(:name => 'Mary', :age => 14)
99
+ }
100
+
101
+ assert_equal %({"1": {"name": "David"}}), contacts.to_json(:only => [1, :name])
102
+ end
103
+
104
+ end
@@ -0,0 +1,211 @@
1
+ require 'test_helper'
2
+ require 'ruby-debug'
3
+ class Address
4
+ include MongoMapper::EmbeddedDocument
5
+
6
+ key :address, String
7
+ key :city, String
8
+ key :state, String
9
+ key :zip, Integer
10
+ end
11
+
12
+ class Project
13
+ include MongoMapper::Document
14
+
15
+ key :name, String
16
+
17
+ many :statuses
18
+ many :addresses
19
+ end
20
+
21
+ class Status
22
+ include MongoMapper::Document
23
+
24
+ belongs_to :project
25
+ belongs_to :target, :polymorphic => true
26
+
27
+ key :name, String
28
+ end
29
+
30
+ class Person
31
+ include MongoMapper::EmbeddedDocument
32
+ key :name, String
33
+ key :child, Person
34
+
35
+ many :pets
36
+ end
37
+
38
+ class Pet
39
+ include MongoMapper::EmbeddedDocument
40
+
41
+ key :name, String
42
+ key :species, String
43
+ end
44
+
45
+ class AssociationsTest < Test::Unit::TestCase
46
+ def setup
47
+ Project.collection.clear
48
+ Status.collection.clear
49
+ end
50
+
51
+ context "Polymorphic Belongs To" do
52
+ should "default to nil" do
53
+ status = Status.new
54
+ status.target.should be_nil
55
+ end
56
+
57
+ should "store the association" do
58
+ status = Status.new
59
+ project = Project.new(:name => "mongomapper")
60
+ status.target = project
61
+ status.save.should be_true
62
+
63
+ from_db = Status.find(status.id)
64
+ from_db.target.should_not be_nil
65
+ from_db.target_id.should == project.id
66
+ from_db.target_type.should == "Project"
67
+ from_db.target.name.should == "mongomapper"
68
+ end
69
+
70
+ should "unset the association" do
71
+ status = Status.new
72
+ project = Project.new(:name => "mongomapper")
73
+ status.target = project
74
+ status.save.should be_true
75
+
76
+ from_db = Status.find(status.id)
77
+ from_db.target = nil
78
+ from_db.target_type.should be_nil
79
+ from_db.target_id.should be_nil
80
+ from_db.target.should be_nil
81
+ end
82
+ end
83
+
84
+ context "Belongs To" do
85
+ should "default to nil" do
86
+ status = Status.new
87
+ status.project.should be_nil
88
+ end
89
+
90
+ should "store the association" do
91
+ status = Status.new
92
+ project = Project.new(:name => "mongomapper")
93
+ status.project = project
94
+ status.save.should be_true
95
+
96
+ from_db = Status.find(status.id)
97
+ from_db.project.should_not be_nil
98
+ from_db.project.name.should == "mongomapper"
99
+ end
100
+
101
+ should "unset the association" do
102
+ status = Status.new
103
+ project = Project.new(:name => "mongomapper")
104
+ status.project = project
105
+ status.save.should be_true
106
+
107
+ from_db = Status.find(status.id)
108
+ from_db.project = nil
109
+ from_db.project.should be_nil
110
+ end
111
+ end
112
+
113
+ context "Many documents" do
114
+ should "default reader to empty array" do
115
+ project = Project.new
116
+ project.statuses.should == []
117
+ end
118
+
119
+ should "allow adding to association like it was an array" do
120
+ project = Project.new
121
+ project.statuses << Status.new
122
+ project.statuses.push Status.new
123
+ project.statuses.size.should == 2
124
+ end
125
+
126
+ should "store the association" do
127
+ project = Project.new
128
+ project.statuses = [Status.new("name" => "ready")]
129
+ project.save.should be_true
130
+
131
+ from_db = Project.find(project.id)
132
+ from_db.statuses.size.should == 1
133
+ from_db.statuses[0].name.should == "ready"
134
+ end
135
+ end
136
+
137
+ context "Many embedded documents" do
138
+ should "default reader to empty array" do
139
+ project = Project.new
140
+ project.addresses.should == []
141
+ end
142
+
143
+ should "allow adding to association like it was an array" do
144
+ project = Project.new
145
+ project.addresses << Address.new
146
+ project.addresses.push Address.new
147
+ project.addresses.size.should == 2
148
+ end
149
+
150
+ should "be embedded in document on save" do
151
+ sb = Address.new(:city => 'South Bend', :state => 'IN')
152
+ chi = Address.new(:city => 'Chicago', :state => 'IL')
153
+ project = Project.new
154
+ project.addresses << sb
155
+ project.addresses << chi
156
+ project.save
157
+
158
+ from_db = Project.find(project.id)
159
+ from_db.addresses.size.should == 2
160
+ from_db.addresses[0].should == sb
161
+ from_db.addresses[1].should == chi
162
+ end
163
+
164
+ should "allow embedding arbitrarily deep" do
165
+ @document = Class.new do
166
+ include MongoMapper::Document
167
+ key :person, Person
168
+ end
169
+
170
+ meg = Person.new(:name => "Meg")
171
+ meg.child = Person.new(:name => "Steve")
172
+ meg.child.child = Person.new(:name => "Linda")
173
+
174
+ doc = @document.new(:person => meg)
175
+ doc.save
176
+
177
+ from_db = @document.find(doc.id)
178
+ from_db.person.name.should == 'Meg'
179
+ from_db.person.child.name.should == 'Steve'
180
+ from_db.person.child.child.name.should == 'Linda'
181
+ end
182
+
183
+ should "allow saving embedded documents in 'many' embedded documents" do
184
+ @document = Class.new do
185
+ include MongoMapper::Document
186
+
187
+ many :people
188
+ end
189
+
190
+ meg = Person.new(:name => "Meg")
191
+ sparky = Pet.new(:name => "Sparky", :species => "Dog")
192
+ koda = Pet.new(:name => "Koda", :species => "Dog")
193
+
194
+ doc = @document.new
195
+
196
+ meg.pets << sparky
197
+ meg.pets << koda
198
+
199
+ doc.people << meg
200
+ doc.save
201
+
202
+ from_db = @document.find(doc.id)
203
+ from_db.people.first.name.should == "Meg"
204
+ from_db.people.first.pets.should_not == []
205
+ from_db.people.first.pets.first.name.should == "Sparky"
206
+ from_db.people.first.pets.first.species.should == "Dog"
207
+ from_db.people.first.pets[1].name.should == "Koda"
208
+ from_db.people.first.pets[1].species.should == "Dog"
209
+ end
210
+ end
211
+ end