djsun-mongomapper 0.3.1.1 → 0.3.3

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