active_mongoid 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.coveralls.yml +1 -0
  4. data/.gitignore +22 -0
  5. data/.ruby_gemset +1 -0
  6. data/.ruby_version +1 -0
  7. data/.travis.yml +11 -0
  8. data/Appraisals +7 -0
  9. data/Gemfile +4 -0
  10. data/LICENSE.txt +22 -0
  11. data/README.md +198 -0
  12. data/Rakefile +7 -0
  13. data/active_mongoid.gemspec +36 -0
  14. data/gemfiles/mongoid_2.8.gemfile +7 -0
  15. data/gemfiles/mongoid_2.8.gemfile.lock +105 -0
  16. data/gemfiles/mongoid_3.1.gemfile +7 -0
  17. data/gemfiles/mongoid_3.1.gemfile.lock +108 -0
  18. data/lib/active_mongoid.rb +8 -0
  19. data/lib/active_mongoid/associations.rb +82 -0
  20. data/lib/active_mongoid/associations/binding.rb +77 -0
  21. data/lib/active_mongoid/associations/builder.rb +26 -0
  22. data/lib/active_mongoid/associations/builders/in.rb +17 -0
  23. data/lib/active_mongoid/associations/builders/many.rb +15 -0
  24. data/lib/active_mongoid/associations/builders/one.rb +15 -0
  25. data/lib/active_mongoid/associations/document_relation/accessors.rb +100 -0
  26. data/lib/active_mongoid/associations/document_relation/associations.rb +33 -0
  27. data/lib/active_mongoid/associations/document_relation/auto_save.rb +31 -0
  28. data/lib/active_mongoid/associations/document_relation/bindings/in.rb +48 -0
  29. data/lib/active_mongoid/associations/document_relation/bindings/many.rb +19 -0
  30. data/lib/active_mongoid/associations/document_relation/bindings/one.rb +19 -0
  31. data/lib/active_mongoid/associations/document_relation/builders.rb +31 -0
  32. data/lib/active_mongoid/associations/document_relation/dependent.rb +26 -0
  33. data/lib/active_mongoid/associations/document_relation/macros.rb +51 -0
  34. data/lib/active_mongoid/associations/document_relation/referenced/in.rb +72 -0
  35. data/lib/active_mongoid/associations/document_relation/referenced/many.rb +125 -0
  36. data/lib/active_mongoid/associations/document_relation/referenced/one.rb +75 -0
  37. data/lib/active_mongoid/associations/many.rb +211 -0
  38. data/lib/active_mongoid/associations/metadata.rb +229 -0
  39. data/lib/active_mongoid/associations/one.rb +21 -0
  40. data/lib/active_mongoid/associations/proxy.rb +38 -0
  41. data/lib/active_mongoid/associations/record_relation/accessors.rb +80 -0
  42. data/lib/active_mongoid/associations/record_relation/associations.rb +33 -0
  43. data/lib/active_mongoid/associations/record_relation/auto_save.rb +43 -0
  44. data/lib/active_mongoid/associations/record_relation/bindings/in.rb +48 -0
  45. data/lib/active_mongoid/associations/record_relation/bindings/many.rb +19 -0
  46. data/lib/active_mongoid/associations/record_relation/bindings/one.rb +19 -0
  47. data/lib/active_mongoid/associations/record_relation/builders.rb +31 -0
  48. data/lib/active_mongoid/associations/record_relation/dependent.rb +26 -0
  49. data/lib/active_mongoid/associations/record_relation/macros.rb +65 -0
  50. data/lib/active_mongoid/associations/record_relation/referenced/in.rb +72 -0
  51. data/lib/active_mongoid/associations/record_relation/referenced/many.rb +128 -0
  52. data/lib/active_mongoid/associations/record_relation/referenced/one.rb +75 -0
  53. data/lib/active_mongoid/associations/targets/enumerable.rb +161 -0
  54. data/lib/active_mongoid/bson_id.rb +44 -0
  55. data/lib/active_mongoid/finder_proxy.rb +55 -0
  56. data/lib/active_mongoid/finders.rb +60 -0
  57. data/lib/active_mongoid/version.rb +3 -0
  58. data/spec/lib/associations/document_relation/accessors_spec.rb +330 -0
  59. data/spec/lib/associations/document_relation/auto_save_spec.rb +157 -0
  60. data/spec/lib/associations/document_relation/bindings/in_spec.rb +39 -0
  61. data/spec/lib/associations/document_relation/bindings/many_spec.rb +36 -0
  62. data/spec/lib/associations/document_relation/bindings/one_spec.rb +39 -0
  63. data/spec/lib/associations/document_relation/builders_spec.rb +117 -0
  64. data/spec/lib/associations/document_relation/dependent_spec.rb +87 -0
  65. data/spec/lib/associations/document_relation/macros_spec.rb +68 -0
  66. data/spec/lib/associations/document_relation/referenced/in_spec.rb +27 -0
  67. data/spec/lib/associations/document_relation/referenced/many_spec.rb +32 -0
  68. data/spec/lib/associations/document_relation/referenced/one_spec.rb +28 -0
  69. data/spec/lib/associations/metadata_spec.rb +157 -0
  70. data/spec/lib/associations/record_relation/accessors_spec.rb +328 -0
  71. data/spec/lib/associations/record_relation/auto_save_spec.rb +157 -0
  72. data/spec/lib/associations/record_relation/bindings/in_spec.rb +39 -0
  73. data/spec/lib/associations/record_relation/bindings/many_spec.rb +39 -0
  74. data/spec/lib/associations/record_relation/bindings/one_spec.rb +57 -0
  75. data/spec/lib/associations/record_relation/builders_spec.rb +118 -0
  76. data/spec/lib/associations/record_relation/dependent_spec.rb +87 -0
  77. data/spec/lib/associations/record_relation/macros_spec.rb +73 -0
  78. data/spec/lib/associations/record_relation/referenced/in_spec.rb +27 -0
  79. data/spec/lib/associations/record_relation/referenced/many_spec.rb +32 -0
  80. data/spec/lib/associations/record_relation/referenced/one_spec.rb +27 -0
  81. data/spec/lib/bson_id_spec.rb +48 -0
  82. data/spec/lib/finders_spec.rb +105 -0
  83. data/spec/spec_helper.rb +89 -0
  84. data/spec/support/models/active_record/address.rb +6 -0
  85. data/spec/support/models/active_record/division.rb +16 -0
  86. data/spec/support/models/active_record/division_setting.rb +9 -0
  87. data/spec/support/models/active_record/player.rb +12 -0
  88. data/spec/support/models/mongoid/league.rb +10 -0
  89. data/spec/support/models/mongoid/person.rb +9 -0
  90. data/spec/support/models/mongoid/post.rb +9 -0
  91. data/spec/support/models/mongoid/stat.rb +8 -0
  92. data/spec/support/models/mongoid/team.rb +9 -0
  93. data/spec/support/shared_examples/shared_many_spec.rb +411 -0
  94. metadata +370 -0
@@ -0,0 +1,21 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ class One < Proxy
4
+
5
+ def clear
6
+ target.delete
7
+ end
8
+
9
+ def respond_to?(name, include_private = false)
10
+ target.respond_to?(name, include_private) || super
11
+ end
12
+
13
+ def ==(other)
14
+ return false unless other
15
+ return true if target.object_id == other.object_id
16
+ return true if target.attributes == other.attributes
17
+ target == other
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ class Proxy
4
+
5
+ instance_methods.each do |method|
6
+ undef_method(method) unless
7
+ method =~ /(^__|^send|^object_id|^respond_to|^tap)/
8
+ end
9
+
10
+ delegate :bind_one, :unbind_one, to: :binding
11
+
12
+ attr_accessor :base, :target, :__metadata__
13
+
14
+ def init(base, target, metadata)
15
+ @base = base
16
+ @target = target
17
+ @__metadata__ = metadata
18
+ yield(self) if block_given?
19
+ end
20
+
21
+ def method_missing(name, *args, &block)
22
+ target.send(name, *args, &block)
23
+ end
24
+
25
+ def klass
26
+ __metadata__ ? __metadata__.klass : nil
27
+ end
28
+
29
+ def ==(other)
30
+ # return false unless other
31
+ # return true if target.object_id == other.object_id
32
+ # return true if target.attributes == other.attributes
33
+ target == other
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,80 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Accessors
5
+ extend ActiveSupport::Concern
6
+
7
+ def build_record(name, object, metadata)
8
+ relation = create_record_relation(object, metadata)
9
+ set_record_relation(name, relation)
10
+ end
11
+
12
+ def set_record_relation(name, object)
13
+ instance_variable_set("@#{name}", object)
14
+ end
15
+
16
+ def create_record_relation(object, metadata)
17
+ type = self.attributes[metadata.inverse_type]
18
+ target = metadata.builder(self, object).build(type)
19
+ target ? metadata.relation.new(self, target, metadata) : nil
20
+ end
21
+
22
+
23
+ private
24
+
25
+ def get_record_relation(name, metadata, object, reload = false)
26
+ if !reload && (value = instance_variable_get("@#{name}")) != nil
27
+ value
28
+ else
29
+ if object && needs_no_database_query?(object, metadata)
30
+ build_record(name, object, metadata)
31
+ else
32
+ build_record(name, attributes.with_indifferent_access[metadata.key].to_s, metadata)
33
+ end
34
+ end
35
+ end
36
+
37
+ def needs_no_database_query?(object, metadata)
38
+ object.is_a?(::ActiveRecord::Base) && object.id == attributes[metadata.key]
39
+ end
40
+
41
+
42
+ module ClassMethods
43
+
44
+ private
45
+
46
+ def existence_check(name)
47
+ module_eval <<-END
48
+ def #{name}?
49
+ !__send__(:#{name}).blank?
50
+ end
51
+ alias :has_#{name}? :#{name}?
52
+ END
53
+ self
54
+ end
55
+
56
+ def record_getter(name, metadata)
57
+ self.instance_eval do
58
+ define_method(name) do |reload = false|
59
+ get_record_relation(name, metadata, nil, reload)
60
+ end
61
+ end
62
+ end
63
+
64
+ def record_setter(name, metadata)
65
+ self.instance_eval do
66
+ define_method("#{name}=") do |object|
67
+ if value = get_record_relation(name, metadata, object)
68
+ set_record_relation(name, value.substitute(object))
69
+ else
70
+ build_record(name, object, metadata)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,33 @@
1
+ require "active_mongoid/associations/record_relation/macros"
2
+ require "active_mongoid/associations/record_relation/accessors"
3
+ require "active_mongoid/associations/record_relation/builders"
4
+ require "active_mongoid/associations/record_relation/auto_save"
5
+ require "active_mongoid/associations/record_relation/dependent"
6
+ require "active_mongoid/associations/record_relation/bindings/one"
7
+ require "active_mongoid/associations/record_relation/bindings/in"
8
+ require "active_mongoid/associations/record_relation/bindings/many"
9
+ require "active_mongoid/associations/record_relation/referenced/one"
10
+ require "active_mongoid/associations/record_relation/referenced/in"
11
+ require "active_mongoid/associations/record_relation/referenced/many"
12
+
13
+ module ActiveMongoid
14
+ module Associations
15
+ module RecordRelation
16
+ module Associations
17
+ extend ActiveSupport::Concern
18
+
19
+ attr_accessor :__metadata__
20
+
21
+ included do
22
+ include RecordRelation::Macros
23
+ include RecordRelation::Accessors
24
+ include RecordRelation::Builders
25
+ include RecordRelation::AutoSave
26
+ include RecordRelation::Dependent
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,43 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module AutoSave
5
+ extend ActiveSupport::Concern
6
+
7
+ def record_changed_for_autosave?(obj)
8
+ obj.new_record? || obj.changed? || obj.marked_for_destruction?
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def autosave_records(metadata)
14
+ if metadata.autosave?
15
+ save_method = :"autosave_records_for_#{metadata.name}"
16
+ define_method(save_method) do
17
+ if relation = instance_variable_get("@#{metadata.name}")
18
+ Array(relation).each { |d| d.save if record_changed_for_autosave?(d) }
19
+ end
20
+ end
21
+ after_save save_method
22
+ end
23
+ autosave_record_id(metadata)
24
+ end
25
+
26
+ def autosave_record_id(metadata)
27
+ if metadata.stores_foreign_key?
28
+ save_method = :"autosave_record_id_for_#{metadata.name}"
29
+ define_method(save_method) do
30
+ if relation = instance_variable_get("@#{metadata.name}")
31
+ self.send(metadata.foreign_key_setter, relation.send(metadata.primary_key))
32
+ end
33
+ end
34
+ before_save save_method
35
+ end
36
+ end
37
+
38
+
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Bindings
5
+ class In < Associations::Binding
6
+
7
+ def bind_one
8
+ check_inverse!(target)
9
+ bind_foreign_key(base, record_id(target))
10
+ bind_polymorphic_inverse_type(base, target.class.name)
11
+ unless _binding?
12
+ _binding do
13
+ if inverse = __metadata__.inverse(target)
14
+ if set_base_metadata
15
+ if base.referenced_many_documents?
16
+ target.__send__(inverse).push(base)
17
+ else
18
+ target.set_document_relation(inverse, base)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def unbind_one
27
+ inverse = __metadata__.inverse(target)
28
+ bind_foreign_key(base, nil)
29
+ bind_polymorphic_inverse_type(base, nil)
30
+ unless _binding?
31
+ _binding do
32
+ if inverse
33
+ set_base_metadata
34
+ if base.referenced_many_documents?
35
+ target.__send__(inverse).delete(base)
36
+ else
37
+ target.set_document_relation(inverse, nil)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Bindings
5
+ class Many < Associations::Binding
6
+
7
+ def bind_one(record)
8
+ bind_from_relational_parent(record)
9
+ end
10
+
11
+ def unbind_one(record)
12
+ unbind_from_relational_parent(record)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Bindings
5
+ class One < Associations::Binding
6
+
7
+ def bind_one
8
+ bind_from_relational_parent(target)
9
+ end
10
+
11
+ def unbind_one
12
+ unbind_from_relational_parent(target)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Builders
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def record_builder(name, metadata)
9
+ define_method("build_#{name}") do |attributes = {}|
10
+ record = metadata.klass.new(attributes)
11
+ send("#{name}=", record)
12
+ end
13
+ self
14
+ end
15
+
16
+ def record_creator(name, metadata)
17
+ define_method("create_#{name}") do |attributes = {}|
18
+ record = metadata.klass.new(attributes)
19
+ obj = send("#{name}=", record)
20
+ record.save
21
+ save if metadata.stores_foreign_key?
22
+ obj
23
+ end
24
+ self
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Dependent
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+
9
+ def dependent_records(metadata)
10
+ if metadata.dependent
11
+ dependent_method = :"dependent_records_for_#{metadata.name}"
12
+ define_method(dependent_method) do
13
+ relation = get_record_relation(metadata.name, metadata, nil, true)
14
+ Array(relation).each { |d| d.send(metadata.dependent) }
15
+ end
16
+
17
+ before_destroy dependent_method
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,65 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Macros
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+
9
+ def belongs_to_record(name, options = {})
10
+ meta = characterize_association(name, Referenced::In, options)
11
+ reference_record(meta)
12
+ relate_one_to_one_record(name, meta)
13
+ end
14
+
15
+ def has_one_record(name, options = {})
16
+ meta = characterize_association(name, Referenced::One, options)
17
+ relate_one_to_one_record(name, meta)
18
+ end
19
+
20
+ def has_many_records(name, options = {})
21
+ meta = characterize_association(name, Referenced::Many, options)
22
+ relate_record(name, meta)
23
+ # document_ids_setter(name, metadata)
24
+ # document_ids_getter(name, metadata)
25
+ end
26
+
27
+ private
28
+
29
+ def reference_record(metadata)
30
+ key = metadata.foreign_key
31
+ if metadata.stores_foreign_key? && !fields.include?(key)
32
+ field(
33
+ key,
34
+ type: Integer,
35
+ default: metadata.foreign_key_default
36
+ )
37
+ if metadata.polymorphic?
38
+ self.polymorphic = true
39
+ field(metadata.inverse_type, type: String)
40
+ end
41
+ end
42
+ end
43
+
44
+ def relate_one_to_one_record(name, metadata)
45
+ relate_record(name, metadata)
46
+ record_builder(name, metadata)
47
+ record_creator(name, metadata)
48
+ end
49
+
50
+
51
+ def relate_record(name, metadata)
52
+ self.am_relations = am_relations.merge(name.to_s => metadata)
53
+ record_getter(name, metadata)
54
+ record_setter(name, metadata)
55
+ autosave_records(metadata)
56
+ dependent_records(metadata)
57
+ existence_check(name)
58
+ end
59
+
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,72 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Referenced
5
+ class In < Associations::One
6
+
7
+ def initialize(base, target, metadata)
8
+ init(base, target, metadata) do
9
+ bind_one
10
+ end
11
+ end
12
+
13
+ def substitute(replacement)
14
+ unbind_one
15
+ return nil unless replacement
16
+ self.target = normalize(replacement)
17
+ bind_one
18
+ self
19
+ end
20
+
21
+ private
22
+
23
+ def binding
24
+ Bindings::In.new(base, target, __metadata__)
25
+ end
26
+
27
+ def normalize(replacement)
28
+ return replacement if replacement.is_a?(::ActiveRecord::Base)
29
+ __metadata__.builder(klass, replacement).build
30
+ end
31
+
32
+ class << self
33
+
34
+ def stores_foreign_key?
35
+ true
36
+ end
37
+
38
+ def foreign_key(name)
39
+ "#{name}#{foreign_key_suffix}"
40
+ end
41
+
42
+ def foreign_key_default
43
+ nil
44
+ end
45
+
46
+ def foreign_key_suffix
47
+ "_id"
48
+ end
49
+
50
+ def primary_key_default
51
+ "id"
52
+ end
53
+
54
+ def macro
55
+ :belongs_to_record
56
+ end
57
+
58
+ def builder(base, meta, object)
59
+ ActiveMongoid::Associations::Builders::In.new(base, meta, object)
60
+ end
61
+
62
+ def criteria(metadata, object, type = nil)
63
+ type.where(metadata.primary_key => object)
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end