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.
Files changed (34) hide show
  1. data/History +20 -1
  2. data/Rakefile +5 -3
  3. data/VERSION +1 -1
  4. data/lib/mongomapper/associations/base.rb +3 -5
  5. data/lib/mongomapper/associations/belongs_to_polymorphic_proxy.rb +5 -3
  6. data/lib/mongomapper/associations/belongs_to_proxy.rb +4 -4
  7. data/lib/mongomapper/associations/many_documents_proxy.rb +32 -14
  8. data/lib/mongomapper/associations/proxy.rb +2 -6
  9. data/lib/mongomapper/associations.rb +38 -15
  10. data/lib/mongomapper/document.rb +165 -95
  11. data/lib/mongomapper/dynamic_finder.rb +38 -0
  12. data/lib/mongomapper/embedded_document.rb +116 -88
  13. data/lib/mongomapper/finder_options.rb +3 -14
  14. data/lib/mongomapper/key.rb +12 -16
  15. data/lib/mongomapper/serializers/json_serializer.rb +15 -12
  16. data/lib/mongomapper/support.rb +30 -0
  17. data/lib/mongomapper.rb +7 -33
  18. data/mongomapper.gemspec +10 -7
  19. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +14 -0
  20. data/test/functional/associations/test_belongs_to_proxy.rb +10 -0
  21. data/test/functional/associations/test_many_polymorphic_proxy.rb +46 -52
  22. data/test/functional/associations/test_many_proxy.rb +71 -12
  23. data/test/functional/test_associations.rb +9 -2
  24. data/test/functional/test_document.rb +281 -20
  25. data/test/functional/test_rails_compatibility.rb +2 -3
  26. data/test/models.rb +39 -8
  27. data/test/unit/serializers/test_json_serializer.rb +46 -12
  28. data/test/unit/test_association_base.rb +10 -2
  29. data/test/unit/test_document.rb +7 -9
  30. data/test/unit/test_embedded_document.rb +180 -24
  31. data/test/unit/test_finder_options.rb +7 -38
  32. data/test/unit/test_key.rb +54 -24
  33. metadata +5 -5
  34. data/test/unit/test_mongo_id.rb +0 -35
data/History CHANGED
@@ -1,8 +1,27 @@
1
- 0.3.2 (master)
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.10.1')
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
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 belongs_to_key_name
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.belongs_to_key_name}=", id)
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
- proxy_class.find(proxy_id) if proxy_id && proxy_class
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.belongs_to_key_name)
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.belongs_to_key_name}=", id)
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.belongs_to_key_name)
17
- @association.klass.find(association_id)
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
- define_association_keys(association)
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 define_association_keys(association)
39
- if association.belongs_to?
40
- key(association.belongs_to_key_name, String)
41
- key(association.type_key_name, String) if association.polymorphic?
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
- if association.many? && association.polymorphic?
45
- association.klass.send(:key, association.type_key_name, String)
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