ramsingla-mongomapper 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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