active_mongoid 0.1.0

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