djsun-mongomapper 0.3.1.1 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History +20 -1
- data/Rakefile +5 -3
- data/VERSION +1 -1
- data/lib/mongomapper/associations/base.rb +3 -5
- data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +5 -3
- data/lib/mongomapper/associations/belongs_to_proxy.rb +4 -4
- data/lib/mongomapper/associations/many_documents_proxy.rb +32 -14
- data/lib/mongomapper/associations/proxy.rb +2 -6
- data/lib/mongomapper/associations.rb +38 -15
- data/lib/mongomapper/document.rb +165 -95
- data/lib/mongomapper/dynamic_finder.rb +38 -0
- data/lib/mongomapper/embedded_document.rb +116 -88
- data/lib/mongomapper/finder_options.rb +3 -14
- data/lib/mongomapper/key.rb +12 -16
- data/lib/mongomapper/serializers/json_serializer.rb +15 -12
- data/lib/mongomapper/support.rb +30 -0
- data/lib/mongomapper.rb +7 -33
- data/mongomapper.gemspec +10 -7
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +14 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +10 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +46 -52
- data/test/functional/associations/test_many_proxy.rb +71 -12
- data/test/functional/test_associations.rb +9 -2
- data/test/functional/test_document.rb +281 -20
- data/test/functional/test_rails_compatibility.rb +2 -3
- data/test/models.rb +39 -8
- data/test/unit/serializers/test_json_serializer.rb +46 -12
- data/test/unit/test_association_base.rb +10 -2
- data/test/unit/test_document.rb +7 -9
- data/test/unit/test_embedded_document.rb +180 -24
- data/test/unit/test_finder_options.rb +7 -38
- data/test/unit/test_key.rb +54 -24
- metadata +5 -5
- data/test/unit/test_mongo_id.rb +0 -35
data/History
CHANGED
@@ -1,8 +1,27 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.4 (master)
|
2
|
+
* BACKWORDS COMPATIBILITY BREAK: Timestamps are now optional. To use them add timestamps! to your model.
|
3
|
+
* BACKWORDS COMPATIBILITY BREAK: Associations keys are no longer created automatically when you use belongs_to and many. Too much was hidden from the developer. You now have to declare them like key :creator_id, String and such.
|
4
|
+
|
5
|
+
0.3.3 8/16/2009
|
6
|
+
* BACKWORDS COMPATIBILITY BREAK: _id is now once again a string rather than an object id and will stay that way.
|
7
|
+
* Custom id's can now be used because of the change to string id's
|
8
|
+
* Added dynamic finders to document. (dcu)
|
9
|
+
* Added destroy_all, delete_all and nullify for many document association
|
10
|
+
* Added :dependent option for many documents assocation (dcu)
|
11
|
+
* update_attributes now returns true or false instead of the document. (Durran Jordan and me)
|
12
|
+
* Keys no longer require a type
|
13
|
+
* Keys can now be added on the fly using []=
|
14
|
+
|
15
|
+
0.3.2 8/6/2009
|
2
16
|
* Added many polymorphic documents association
|
3
17
|
* Implemented build and create for many and many polymorphic documents
|
4
18
|
* <<, push and concat now work correctly for many and many polymorphic documents
|
5
19
|
* find(:first) now accepts order option
|
20
|
+
* id is now included by default with to_json
|
21
|
+
* _id is now always excluded from to_json
|
22
|
+
* Times are now always returned as UTC
|
23
|
+
* Default values are now a bit more intelligent for Array and Hash keys (djsun)
|
24
|
+
* Embedded documents now have _id as well so they can be identified more easily
|
6
25
|
|
7
26
|
0.3.1 7/28/2009
|
8
27
|
* 1 minor tweak
|
data/Rakefile
CHANGED
@@ -12,14 +12,16 @@ begin
|
|
12
12
|
gem.rubyforge_project = "mongomapper"
|
13
13
|
|
14
14
|
gem.add_dependency('activesupport')
|
15
|
-
gem.add_dependency('mongodb-mongo', '0.
|
15
|
+
gem.add_dependency('mongodb-mongo', '0.11.1')
|
16
16
|
gem.add_dependency('jnunemaker-validatable', '1.7.2')
|
17
17
|
|
18
18
|
gem.add_development_dependency('mocha', '0.9.4')
|
19
19
|
gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
|
20
20
|
end
|
21
|
-
|
22
|
-
Jeweler::RubyforgeTasks.new
|
21
|
+
|
22
|
+
Jeweler::RubyforgeTasks.new do |rubyforge|
|
23
|
+
rubyforge.doc_task = "rdoc"
|
24
|
+
end
|
23
25
|
rescue LoadError
|
24
26
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
25
27
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.3
|
@@ -4,9 +4,7 @@ module MongoMapper
|
|
4
4
|
attr_reader :type, :name, :options
|
5
5
|
|
6
6
|
def initialize(type, name, options = {})
|
7
|
-
@options = options
|
8
|
-
@type = type
|
9
|
-
@name = name
|
7
|
+
@type, @name, @options = type, name, options
|
10
8
|
end
|
11
9
|
|
12
10
|
def class_name
|
@@ -41,8 +39,8 @@ module MongoMapper
|
|
41
39
|
@type_key_name ||= many? ? '_type' : "#{name}_type"
|
42
40
|
end
|
43
41
|
|
44
|
-
def
|
45
|
-
"#{name}_id"
|
42
|
+
def foreign_key
|
43
|
+
@options[:foreign_key] || "#{name}_id"
|
46
44
|
end
|
47
45
|
|
48
46
|
def ivar
|
@@ -7,18 +7,20 @@ module MongoMapper
|
|
7
7
|
id, type = doc.id, doc.class.name
|
8
8
|
end
|
9
9
|
|
10
|
-
@owner.send("#{@association.
|
10
|
+
@owner.send("#{@association.foreign_key}=", id)
|
11
11
|
@owner.send("#{@association.type_key_name}=", type)
|
12
12
|
reset
|
13
13
|
end
|
14
14
|
|
15
15
|
protected
|
16
16
|
def find_target
|
17
|
-
|
17
|
+
if proxy_id && proxy_class
|
18
|
+
proxy_class.find_by_id(proxy_id)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
def proxy_id
|
21
|
-
@proxy_id ||= @owner.send(@association.
|
23
|
+
@proxy_id ||= @owner.send(@association.foreign_key)
|
22
24
|
end
|
23
25
|
|
24
26
|
def proxy_class
|
@@ -7,14 +7,14 @@ module MongoMapper
|
|
7
7
|
id = doc.id
|
8
8
|
end
|
9
9
|
|
10
|
-
@owner.send("#{@association.
|
10
|
+
@owner.send("#{@association.foreign_key}=", id)
|
11
11
|
reset
|
12
12
|
end
|
13
13
|
|
14
|
-
protected
|
14
|
+
protected
|
15
15
|
def find_target
|
16
|
-
if association_id = @owner.send(@association.
|
17
|
-
@association.klass.
|
16
|
+
if association_id = @owner.send(@association.foreign_key)
|
17
|
+
@association.klass.find_by_id(association_id)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -2,38 +2,38 @@ module MongoMapper
|
|
2
2
|
module Associations
|
3
3
|
class ManyDocumentsProxy < Proxy
|
4
4
|
delegate :klass, :to => :@association
|
5
|
-
|
5
|
+
|
6
6
|
def find(*args)
|
7
7
|
options = args.extract_options!
|
8
8
|
klass.find(*args << scoped_options(options))
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def paginate(options)
|
12
12
|
klass.paginate(scoped_options(options))
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def all(options={})
|
16
16
|
find(:all, scoped_options(options))
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def first(options={})
|
20
20
|
find(:first, scoped_options(options))
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def last(options={})
|
24
24
|
find(:last, scoped_options(options))
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def count(conditions={})
|
28
28
|
klass.count(conditions.deep_merge(scoped_conditions))
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def replace(docs)
|
32
32
|
@target.map(&:destroy) if load_target
|
33
33
|
docs.each { |doc| apply_scope(doc).save }
|
34
34
|
reset
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def <<(*docs)
|
38
38
|
ensure_owner_saved
|
39
39
|
flatten_deeper(docs).each { |doc| apply_scope(doc).save }
|
@@ -41,36 +41,54 @@ module MongoMapper
|
|
41
41
|
end
|
42
42
|
alias_method :push, :<<
|
43
43
|
alias_method :concat, :<<
|
44
|
-
|
44
|
+
|
45
45
|
def build(attrs={})
|
46
46
|
doc = klass.new(attrs)
|
47
47
|
apply_scope(doc)
|
48
48
|
doc
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
def create(attrs={})
|
52
52
|
doc = klass.new(attrs)
|
53
53
|
apply_scope(doc).save
|
54
54
|
doc
|
55
55
|
end
|
56
|
+
|
57
|
+
def destroy_all(conditions={})
|
58
|
+
all(:conditions => conditions).map(&:destroy)
|
59
|
+
reset
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_all(conditions={})
|
63
|
+
klass.delete_all(conditions.deep_merge(scoped_conditions))
|
64
|
+
reset
|
65
|
+
end
|
56
66
|
|
67
|
+
def nullify
|
68
|
+
criteria = FinderOptions.to_mongo_criteria(scoped_conditions)
|
69
|
+
all(criteria).each do |doc|
|
70
|
+
doc.update_attributes self.foreign_key => nil
|
71
|
+
end
|
72
|
+
reset
|
73
|
+
end
|
74
|
+
|
57
75
|
protected
|
58
76
|
def scoped_conditions
|
59
77
|
{self.foreign_key => @owner.id}
|
60
78
|
end
|
61
|
-
|
79
|
+
|
62
80
|
def scoped_options(options)
|
63
81
|
options.deep_merge({:conditions => scoped_conditions})
|
64
82
|
end
|
65
|
-
|
83
|
+
|
66
84
|
def find_target
|
67
85
|
find(:all)
|
68
86
|
end
|
69
|
-
|
87
|
+
|
70
88
|
def ensure_owner_saved
|
71
89
|
@owner.save if @owner.new?
|
72
90
|
end
|
73
|
-
|
91
|
+
|
74
92
|
def apply_scope(doc)
|
75
93
|
ensure_owner_saved
|
76
94
|
doc.send("#{self.foreign_key}=", @owner.id)
|
@@ -1,12 +1,8 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module Associations
|
3
|
-
class Proxy
|
3
|
+
class Proxy < BasicObject
|
4
4
|
attr_reader :owner, :association
|
5
|
-
|
6
|
-
instance_methods.each do |m|
|
7
|
-
undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/
|
8
|
-
end
|
9
|
-
|
5
|
+
|
10
6
|
def initialize(owner, association)
|
11
7
|
@owner = owner
|
12
8
|
@association = association
|
@@ -2,12 +2,12 @@ module MongoMapper
|
|
2
2
|
module Associations
|
3
3
|
module ClassMethods
|
4
4
|
def belongs_to(association_id, options = {})
|
5
|
-
create_association(:belongs_to, association_id, options)
|
5
|
+
create_association(:belongs_to, association_id, options)
|
6
6
|
self
|
7
7
|
end
|
8
8
|
|
9
9
|
def many(association_id, options = {})
|
10
|
-
create_association(:many, association_id, options)
|
10
|
+
create_association(:many, association_id, options)
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
@@ -20,29 +20,52 @@ module MongoMapper
|
|
20
20
|
association = Associations::Base.new(type, name, options)
|
21
21
|
associations[association.name] = association
|
22
22
|
define_association_methods(association)
|
23
|
-
|
23
|
+
define_dependent_callback(association)
|
24
24
|
association
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def define_association_methods(association)
|
28
28
|
define_method(association.name) do
|
29
29
|
get_proxy(association)
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
define_method("#{association.name}=") do |value|
|
33
33
|
get_proxy(association).replace(value)
|
34
34
|
value
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
38
|
-
def
|
39
|
-
if association.
|
40
|
-
|
41
|
-
|
37
|
+
|
38
|
+
def define_dependent_callback(association)
|
39
|
+
if association.options[:dependent]
|
40
|
+
if association.many?
|
41
|
+
define_dependent_callback_for_many(association)
|
42
|
+
elsif association.belongs_to?
|
43
|
+
define_dependent_callback_for_belongs_to(association)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_dependent_callback_for_many(association)
|
49
|
+
return if association.embeddable?
|
50
|
+
|
51
|
+
after_destroy do |doc|
|
52
|
+
case association.options[:dependent]
|
53
|
+
when :destroy
|
54
|
+
doc.get_proxy(association).destroy_all
|
55
|
+
when :delete_all
|
56
|
+
doc.get_proxy(association).delete_all
|
57
|
+
when :nullify
|
58
|
+
doc.get_proxy(association).nullify
|
59
|
+
end
|
42
60
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
61
|
+
end
|
62
|
+
|
63
|
+
def define_dependent_callback_for_belongs_to(association)
|
64
|
+
after_destroy do |doc|
|
65
|
+
case association.options[:dependent]
|
66
|
+
when :destroy
|
67
|
+
doc.get_proxy(association).destroy
|
68
|
+
end
|
46
69
|
end
|
47
70
|
end
|
48
71
|
end
|
@@ -51,9 +74,9 @@ module MongoMapper
|
|
51
74
|
def get_proxy(association)
|
52
75
|
unless proxy = self.instance_variable_get(association.ivar)
|
53
76
|
proxy = association.proxy_class.new(self, association)
|
54
|
-
self.instance_variable_set(association.ivar, proxy)
|
77
|
+
self.instance_variable_set(association.ivar, proxy) if !frozen?
|
55
78
|
end
|
56
|
-
|
79
|
+
|
57
80
|
proxy
|
58
81
|
end
|
59
82
|
end
|