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,128 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Referenced
5
+ class Many < Associations::Many
6
+
7
+ private
8
+
9
+ def criteria
10
+ Many.criteria(__metadata__, base.send(__metadata__.primary_key), base.class)
11
+ end
12
+
13
+ def binding
14
+ Bindings::Many.new(base, target, __metadata__)
15
+ end
16
+
17
+ # TODO: look into AR analog to collection insert
18
+ def persist_delayed(objs, inserts)
19
+ unless objs.empty?
20
+ # collection.insert(inserts)
21
+ inserts.each do |insert|
22
+ insert.save
23
+ end
24
+ objs.each do |obj|
25
+ # obj.save
26
+ # obj.post_persist
27
+ end
28
+ end
29
+ end
30
+
31
+ def save_or_delay(obj, objs, inserts)
32
+ if obj.new_record? && obj.valid?(:create)
33
+ # obj.run_before_callbacks(:save, :create)
34
+ obj.save
35
+ objs.push(obj)
36
+ inserts.push(obj)
37
+ else
38
+ obj.save
39
+ end
40
+ end
41
+
42
+ def remove_all(conditions = nil, method = :delete_all)
43
+ conditions = conditions || {}
44
+ removed = klass.send(method, conditions.merge!(criteria.where_values_hash))
45
+ target.delete_if do |obj|
46
+ if matches?(obj, conditions)
47
+ unbind_one(obj) and true
48
+ end
49
+ end
50
+ removed
51
+ end
52
+
53
+ def matches?(obj, conditions)
54
+ conditions.all? {|key, value| obj.attributes[key] == value}
55
+ end
56
+
57
+ def remove_not_in(ids)
58
+ removed = criteria.where("id not in (?)", ids)
59
+ if __metadata__.destructive?
60
+ removed.delete_all
61
+ else
62
+ removed.update_all(__metadata__.foreign_key => nil)
63
+ end
64
+ in_memory.each do |obj|
65
+ if !ids.include?(obj.id)
66
+ unbind_one(obj)
67
+ target.delete(obj)
68
+ if __metadata__.destructive?
69
+ obj.mark_for_destruction
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def method_missing(name, *args, &block)
76
+ if target.respond_to?(name)
77
+ target.send(name, *args, &block)
78
+ else
79
+ criteria.scoping do
80
+ criteria.public_send(name, *args, &block)
81
+ end
82
+ end
83
+ end
84
+
85
+ class << self
86
+
87
+ def stores_foreign_key?
88
+ false
89
+ end
90
+
91
+ def foreign_key(name)
92
+ "#{name}#{foreign_key_suffix}"
93
+ end
94
+
95
+ def foreign_key_default
96
+ nil
97
+ end
98
+
99
+ def foreign_key_suffix
100
+ "_id"
101
+ end
102
+
103
+ def primary_key_default
104
+ "_id"
105
+ end
106
+
107
+ def macro
108
+ :has_many_records
109
+ end
110
+
111
+ def builder(base, meta, object)
112
+ ActiveMongoid::Associations::Builders::Many.new(base, meta, object || [])
113
+ end
114
+
115
+ def criteria(metadata, object, type = nil)
116
+ crit = metadata.klass.where(metadata.foreign_key => object.to_s)
117
+ if metadata.polymorphic?
118
+ crit = crit.where(metadata.type => type.name)
119
+ end
120
+ crit
121
+ end
122
+
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,75 @@
1
+ module ActiveMongoid
2
+ module Associations
3
+ module RecordRelation
4
+ module Referenced
5
+ class One < 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
+ if base.persisted?
16
+ if __metadata__.destructive?
17
+ send(__metadata__.dependent)
18
+ else
19
+ save if persisted?
20
+ end
21
+ end
22
+ One.new(base, replacement, __metadata__) if replacement
23
+ end
24
+
25
+ private
26
+
27
+ def binding
28
+ Bindings::One.new(base, target, __metadata__)
29
+ end
30
+
31
+ class << self
32
+
33
+ def stores_foreign_key?
34
+ false
35
+ end
36
+
37
+ def foreign_key(name)
38
+ "#{name}#{foreign_key_suffix}"
39
+ end
40
+
41
+ def foreign_key_default
42
+ nil
43
+ end
44
+
45
+ def foreign_key_suffix
46
+ "_id"
47
+ end
48
+
49
+ def primary_key_default
50
+ "_id"
51
+ end
52
+
53
+ def macro
54
+ :has_one_record
55
+ end
56
+
57
+ def builder(base, meta, object)
58
+ ActiveMongoid::Associations::Builders::One.new(base, meta, object)
59
+ end
60
+
61
+ def criteria(metadata, object, type = nil)
62
+ crit = metadata.klass.where(metadata.foreign_key => object)
63
+ if metadata.polymorphic?
64
+ crit = crit.where(metadata.type => type.name)
65
+ end
66
+ crit
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,161 @@
1
+ require 'mongoid'
2
+
3
+ module ActiveMongoid
4
+ module Associations
5
+ module Targets
6
+ class Enumerable
7
+ include ::Enumerable
8
+
9
+ attr_accessor :added, :loaded, :unloaded
10
+
11
+ delegate :===, :is_a?, :kind_of?, :to => :added
12
+
13
+ def ==(other)
14
+ return false unless other.respond_to?(:entries)
15
+ entries == other.entries
16
+ end
17
+
18
+ def <<(document)
19
+ added.push(document)
20
+ end
21
+ alias :push :<<
22
+
23
+ def clear
24
+ if block_given?
25
+ in_memory { |doc| yield(doc) }
26
+ end
27
+ loaded.clear and added.clear
28
+ end
29
+
30
+ def clone
31
+ collect { |doc| doc.clone }
32
+ end
33
+
34
+ def delete(document)
35
+ (loaded.delete_one(document) || added.delete_one(document)).tap do |doc|
36
+ unless doc
37
+ key = document.is_a?(::Mongoid::Document) ? :_id : :id
38
+ if unloaded && unloaded.where(key => document.id).exists?
39
+ yield(document) if block_given?
40
+ return document
41
+ end
42
+ end
43
+ yield(doc) if block_given?
44
+ end
45
+ end
46
+
47
+ def delete_if(&block)
48
+ load_all!
49
+ tap do
50
+ loaded.delete_if(&block)
51
+ added.delete_if(&block)
52
+ end
53
+ end
54
+
55
+ def each
56
+ if loaded?
57
+ loaded.each do |doc|
58
+ yield(doc)
59
+ end
60
+ else
61
+ unloaded.each do |doc|
62
+ document = added.delete(doc) || loaded.delete(doc) || doc
63
+ yield(document)
64
+ loaded.push(document)
65
+ end
66
+ end
67
+ added.each do |doc|
68
+ yield(doc)
69
+ end
70
+ @executed = true
71
+ end
72
+
73
+ def empty?
74
+ if loaded?
75
+ in_memory.count == 0
76
+ else
77
+ unloaded.count + added.count == 0
78
+ end
79
+ end
80
+
81
+ def first
82
+ added.first || (loaded? ? loaded.first : unloaded.first)
83
+ end
84
+
85
+ def initialize(target)
86
+ if target.is_a?(::Mongoid::Criteria) || target.is_a?(::ActiveRecord::Relation)
87
+ @added, @loaded, @unloaded = [], [], target
88
+ else
89
+ @added, @executed, @loaded = [], true, target
90
+ end
91
+ end
92
+
93
+ def inspect
94
+ entries.inspect
95
+ end
96
+
97
+ def in_memory
98
+ (loaded + added).tap do |docs|
99
+ docs.each { |doc| yield(doc) } if block_given?
100
+ end
101
+ end
102
+
103
+ def last
104
+ added.last || (loaded? ? loaded.last : unloaded.last)
105
+ end
106
+
107
+ alias :load_all! :entries
108
+
109
+ def loaded?
110
+ !!@executed
111
+ end
112
+
113
+ def reset
114
+ loaded.clear and added.clear
115
+ @executed = false
116
+ end
117
+
118
+ def respond_to?(name, include_private = false)
119
+ [].respond_to?(name, include_private) || super
120
+ end
121
+
122
+ def size
123
+ count = (unloaded ? unloaded.count : loaded.count)
124
+ if count.zero?
125
+ count + added.count
126
+ else
127
+ count + added.count{ |d| d.new_record? }
128
+ end
129
+ end
130
+ alias :length :size
131
+
132
+ def to_json(options = {})
133
+ entries.to_json(options)
134
+ end
135
+
136
+ def as_json(options = {})
137
+ entries.as_json(options)
138
+ end
139
+
140
+ def uniq
141
+ entries.uniq
142
+ end
143
+
144
+ def where(opts = :chain, *rest)
145
+ if unloaded.is_a?(::Mongoid::Criteria) || unloaded.is_a?(::ActiveRecord::Relation)
146
+ unloaded.where(opts, *rest)
147
+ else
148
+ raise NoMethodError
149
+ end
150
+ end
151
+
152
+ private
153
+
154
+ def method_missing(name, *args, &block)
155
+ entries.send(name, *args, &block)
156
+ end
157
+
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,44 @@
1
+ module ActiveMongoid
2
+ module BsonId
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+
7
+ def bsonify_attr(name, options = {})
8
+ bson_attr_setter(name)
9
+ bson_attr_getter(name)
10
+ bson_attr_init(name) if options[:initialize]
11
+ end
12
+
13
+ private
14
+
15
+ def bson_attr_setter(name)
16
+ self.instance_eval do
17
+ define_method("#{name}=") do |object|
18
+ attribute = object.nil? ? nil : object.to_s
19
+ write_attribute(name, attribute)
20
+ end
21
+ end
22
+ end
23
+
24
+ def bson_attr_getter(name)
25
+ self.instance_eval do
26
+ define_method(name) do
27
+ attribute = read_attribute(name)
28
+ attribute.nil? ? nil : ::ActiveMongoid::BSON::ObjectId.from_string(attribute)
29
+ end
30
+ end
31
+ end
32
+
33
+ def bson_attr_init(name)
34
+ init_method = :"init_attr_for_#{name}"
35
+ define_method(init_method) do
36
+ self.send("#{name}=", ::ActiveMongoid::BSON::ObjectId.new) unless read_attribute(name)
37
+ end
38
+ after_initialize init_method
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ module ActiveMongoid
2
+ class FinderProxy
3
+ instance_methods.each do |method|
4
+ undef_method(method) unless method =~ /(^__|^object_id|^tap)/
5
+ end
6
+
7
+ attr_accessor :__target
8
+ attr_accessor :__target_class
9
+
10
+
11
+ def initialize(target)
12
+ @__target = target
13
+ @__target_class = target.respond_to?(:klass) ? target.klass : target
14
+ end
15
+
16
+ def find(*args)
17
+ key = args.flatten.first
18
+ if !key.is_a?(Fixnum) && (key.is_a?(::ActiveMongoid::BSON::ObjectId) || ::ActiveMongoid::BSON::ObjectId.legal?(key))
19
+ where({_id: key.to_s}).first.tap do |obj|
20
+ raise ActiveRecord::RecordNotFound unless obj
21
+ end
22
+ else
23
+ FinderProxy.new(__target.send(:find, *args))
24
+ end
25
+ end
26
+
27
+ def where(opts = :chain, *rest)
28
+ if opts && opts.is_a?(Hash)
29
+ bson_opts = opts.select{|k,v| v.is_a?(::ActiveMongoid::BSON::ObjectId)}
30
+
31
+ if bson_opts[:id]
32
+ opts.delete(:id)
33
+ bson_opts[:_id] = bson_opts.delete(:id)
34
+ end
35
+
36
+ bson_opts.each do |k,v|
37
+ bson_opts[k] = v.to_s
38
+ end
39
+
40
+ opts.merge!(bson_opts)
41
+ end
42
+ FinderProxy.new(__target.send(:where, opts, *rest))
43
+ end
44
+
45
+ def method_missing(name, *args, &block)
46
+ resp = __target.send(name, *args, &block)
47
+ if resp == __target_class || (resp.is_a?(ActiveRecord::Relation) && resp.klass == __target_class)
48
+ FinderProxy.new(resp)
49
+ else
50
+ resp
51
+ end
52
+ end
53
+
54
+ end
55
+ end