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