mongoid-locomotive 2.0.0.beta9

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 (274) hide show
  1. data/MIT_LICENSE +20 -0
  2. data/README.rdoc +47 -0
  3. data/lib/mongoid.rb +141 -0
  4. data/lib/mongoid/associations.rb +306 -0
  5. data/lib/mongoid/associations/embedded_in.rb +74 -0
  6. data/lib/mongoid/associations/embeds_many.rb +280 -0
  7. data/lib/mongoid/associations/embeds_one.rb +97 -0
  8. data/lib/mongoid/associations/foreign_key.rb +35 -0
  9. data/lib/mongoid/associations/meta_data.rb +38 -0
  10. data/lib/mongoid/associations/options.rb +62 -0
  11. data/lib/mongoid/associations/proxy.rb +33 -0
  12. data/lib/mongoid/associations/referenced_in.rb +59 -0
  13. data/lib/mongoid/associations/references_many.rb +245 -0
  14. data/lib/mongoid/associations/references_many_as_array.rb +78 -0
  15. data/lib/mongoid/associations/references_one.rb +99 -0
  16. data/lib/mongoid/atomicity.rb +55 -0
  17. data/lib/mongoid/attributes.rb +242 -0
  18. data/lib/mongoid/callbacks.rb +21 -0
  19. data/lib/mongoid/collection.rb +120 -0
  20. data/lib/mongoid/collections.rb +71 -0
  21. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  22. data/lib/mongoid/collections/master.rb +29 -0
  23. data/lib/mongoid/collections/operations.rb +41 -0
  24. data/lib/mongoid/collections/slaves.rb +45 -0
  25. data/lib/mongoid/components.rb +34 -0
  26. data/lib/mongoid/config.rb +263 -0
  27. data/lib/mongoid/contexts.rb +24 -0
  28. data/lib/mongoid/contexts/enumerable.rb +156 -0
  29. data/lib/mongoid/contexts/ids.rb +25 -0
  30. data/lib/mongoid/contexts/mongo.rb +285 -0
  31. data/lib/mongoid/contexts/paging.rb +50 -0
  32. data/lib/mongoid/criteria.rb +248 -0
  33. data/lib/mongoid/criterion/complex.rb +21 -0
  34. data/lib/mongoid/criterion/exclusion.rb +65 -0
  35. data/lib/mongoid/criterion/inclusion.rb +110 -0
  36. data/lib/mongoid/criterion/optional.rb +189 -0
  37. data/lib/mongoid/cursor.rb +81 -0
  38. data/lib/mongoid/deprecation.rb +21 -0
  39. data/lib/mongoid/dirty.rb +252 -0
  40. data/lib/mongoid/document.rb +210 -0
  41. data/lib/mongoid/errors.rb +131 -0
  42. data/lib/mongoid/extensions.rb +115 -0
  43. data/lib/mongoid/extensions/array/accessors.rb +17 -0
  44. data/lib/mongoid/extensions/array/assimilation.rb +26 -0
  45. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  46. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  47. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  48. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  49. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  50. data/lib/mongoid/extensions/date/conversions.rb +24 -0
  51. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  52. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  53. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  54. data/lib/mongoid/extensions/hash/accessors.rb +42 -0
  55. data/lib/mongoid/extensions/hash/assimilation.rb +40 -0
  56. data/lib/mongoid/extensions/hash/conversions.rb +42 -0
  57. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  58. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  59. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  60. data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
  61. data/lib/mongoid/extensions/object/conversions.rb +21 -0
  62. data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
  63. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  64. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  65. data/lib/mongoid/extensions/string/conversions.rb +15 -0
  66. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  67. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  68. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  69. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  70. data/lib/mongoid/extras.rb +61 -0
  71. data/lib/mongoid/factory.rb +20 -0
  72. data/lib/mongoid/field.rb +83 -0
  73. data/lib/mongoid/fields.rb +62 -0
  74. data/lib/mongoid/finders.rb +145 -0
  75. data/lib/mongoid/hierarchy.rb +74 -0
  76. data/lib/mongoid/identity.rb +47 -0
  77. data/lib/mongoid/indexes.rb +27 -0
  78. data/lib/mongoid/javascript.rb +21 -0
  79. data/lib/mongoid/javascript/functions.yml +37 -0
  80. data/lib/mongoid/logger.rb +19 -0
  81. data/lib/mongoid/matchers.rb +35 -0
  82. data/lib/mongoid/matchers/all.rb +11 -0
  83. data/lib/mongoid/matchers/default.rb +26 -0
  84. data/lib/mongoid/matchers/exists.rb +13 -0
  85. data/lib/mongoid/matchers/gt.rb +11 -0
  86. data/lib/mongoid/matchers/gte.rb +11 -0
  87. data/lib/mongoid/matchers/in.rb +11 -0
  88. data/lib/mongoid/matchers/lt.rb +11 -0
  89. data/lib/mongoid/matchers/lte.rb +11 -0
  90. data/lib/mongoid/matchers/ne.rb +11 -0
  91. data/lib/mongoid/matchers/nin.rb +11 -0
  92. data/lib/mongoid/matchers/size.rb +11 -0
  93. data/lib/mongoid/memoization.rb +33 -0
  94. data/lib/mongoid/named_scope.rb +37 -0
  95. data/lib/mongoid/paranoia.rb +106 -0
  96. data/lib/mongoid/paths.rb +61 -0
  97. data/lib/mongoid/persistence.rb +216 -0
  98. data/lib/mongoid/persistence/command.rb +39 -0
  99. data/lib/mongoid/persistence/insert.rb +48 -0
  100. data/lib/mongoid/persistence/insert_embedded.rb +44 -0
  101. data/lib/mongoid/persistence/remove.rb +39 -0
  102. data/lib/mongoid/persistence/remove_all.rb +38 -0
  103. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  104. data/lib/mongoid/persistence/update.rb +71 -0
  105. data/lib/mongoid/railtie.rb +67 -0
  106. data/lib/mongoid/railties/database.rake +60 -0
  107. data/lib/mongoid/scope.rb +75 -0
  108. data/lib/mongoid/state.rb +32 -0
  109. data/lib/mongoid/timestamps.rb +27 -0
  110. data/lib/mongoid/validations.rb +51 -0
  111. data/lib/mongoid/validations/associated.rb +32 -0
  112. data/lib/mongoid/validations/locale/en.yml +5 -0
  113. data/lib/mongoid/validations/uniqueness.rb +56 -0
  114. data/lib/mongoid/version.rb +4 -0
  115. data/lib/mongoid/versioning.rb +26 -0
  116. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  117. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  118. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  119. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  120. data/lib/rails/generators/mongoid_generator.rb +61 -0
  121. data/spec/integration/mongoid/association_attributes_spec.rb +71 -0
  122. data/spec/integration/mongoid/associations_spec.rb +768 -0
  123. data/spec/integration/mongoid/attributes_spec.rb +59 -0
  124. data/spec/integration/mongoid/callback_spec.rb +33 -0
  125. data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
  126. data/spec/integration/mongoid/criteria_spec.rb +281 -0
  127. data/spec/integration/mongoid/dirty_spec.rb +85 -0
  128. data/spec/integration/mongoid/document_spec.rb +741 -0
  129. data/spec/integration/mongoid/extensions_spec.rb +22 -0
  130. data/spec/integration/mongoid/finders_spec.rb +119 -0
  131. data/spec/integration/mongoid/inheritance_spec.rb +171 -0
  132. data/spec/integration/mongoid/named_scope_spec.rb +58 -0
  133. data/spec/integration/mongoid/paranoia_spec.rb +44 -0
  134. data/spec/integration/mongoid/persistence/update_spec.rb +46 -0
  135. data/spec/integration/mongoid/persistence_spec.rb +311 -0
  136. data/spec/integration/mongoid/validations/uniqueness_spec.rb +206 -0
  137. data/spec/models/account.rb +5 -0
  138. data/spec/models/address.rb +40 -0
  139. data/spec/models/agent.rb +7 -0
  140. data/spec/models/animal.rb +15 -0
  141. data/spec/models/answer.rb +4 -0
  142. data/spec/models/callbacks.rb +47 -0
  143. data/spec/models/category.rb +13 -0
  144. data/spec/models/comment.rb +10 -0
  145. data/spec/models/country_code.rb +6 -0
  146. data/spec/models/employer.rb +5 -0
  147. data/spec/models/favorite.rb +8 -0
  148. data/spec/models/game.rb +9 -0
  149. data/spec/models/inheritance.rb +72 -0
  150. data/spec/models/location.rb +5 -0
  151. data/spec/models/login.rb +6 -0
  152. data/spec/models/mixed_drink.rb +4 -0
  153. data/spec/models/name.rb +13 -0
  154. data/spec/models/namespacing.rb +11 -0
  155. data/spec/models/paranoid_post.rb +18 -0
  156. data/spec/models/parents.rb +32 -0
  157. data/spec/models/patient.rb +15 -0
  158. data/spec/models/person.rb +106 -0
  159. data/spec/models/pet.rb +7 -0
  160. data/spec/models/pet_owner.rb +6 -0
  161. data/spec/models/phone.rb +7 -0
  162. data/spec/models/post.rb +25 -0
  163. data/spec/models/preference.rb +7 -0
  164. data/spec/models/question.rb +8 -0
  165. data/spec/models/survey.rb +6 -0
  166. data/spec/models/translation.rb +5 -0
  167. data/spec/models/user.rb +6 -0
  168. data/spec/models/user_accout.rb +5 -0
  169. data/spec/models/vet_visit.rb +5 -0
  170. data/spec/models/video.rb +5 -0
  171. data/spec/spec_helper.rb +33 -0
  172. data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
  173. data/spec/unit/mongoid/associations/embeds_many_spec.rb +626 -0
  174. data/spec/unit/mongoid/associations/embeds_one_spec.rb +287 -0
  175. data/spec/unit/mongoid/associations/foreign_key_spec.rb +90 -0
  176. data/spec/unit/mongoid/associations/meta_data_spec.rb +110 -0
  177. data/spec/unit/mongoid/associations/options_spec.rb +215 -0
  178. data/spec/unit/mongoid/associations/referenced_in_spec.rb +145 -0
  179. data/spec/unit/mongoid/associations/references_many_as_array_spec.rb +424 -0
  180. data/spec/unit/mongoid/associations/references_many_spec.rb +502 -0
  181. data/spec/unit/mongoid/associations/references_one_spec.rb +204 -0
  182. data/spec/unit/mongoid/associations_spec.rb +688 -0
  183. data/spec/unit/mongoid/atomicity_spec.rb +164 -0
  184. data/spec/unit/mongoid/attributes_spec.rb +646 -0
  185. data/spec/unit/mongoid/callbacks_spec.rb +85 -0
  186. data/spec/unit/mongoid/collection_spec.rb +187 -0
  187. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  188. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  189. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  190. data/spec/unit/mongoid/collections_spec.rb +98 -0
  191. data/spec/unit/mongoid/config_spec.rb +298 -0
  192. data/spec/unit/mongoid/contexts/enumerable_spec.rb +447 -0
  193. data/spec/unit/mongoid/contexts/mongo_spec.rb +703 -0
  194. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  195. data/spec/unit/mongoid/criteria_spec.rb +873 -0
  196. data/spec/unit/mongoid/criterion/complex_spec.rb +17 -0
  197. data/spec/unit/mongoid/criterion/exclusion_spec.rb +121 -0
  198. data/spec/unit/mongoid/criterion/inclusion_spec.rb +274 -0
  199. data/spec/unit/mongoid/criterion/optional_spec.rb +483 -0
  200. data/spec/unit/mongoid/cursor_spec.rb +80 -0
  201. data/spec/unit/mongoid/deprecation_spec.rb +24 -0
  202. data/spec/unit/mongoid/dirty_spec.rb +430 -0
  203. data/spec/unit/mongoid/document_spec.rb +623 -0
  204. data/spec/unit/mongoid/errors_spec.rb +154 -0
  205. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  206. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  207. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +52 -0
  208. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  209. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +36 -0
  210. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  211. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  212. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +145 -0
  213. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +14 -0
  214. data/spec/unit/mongoid/extensions/false_class/equality_spec.rb +35 -0
  215. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  216. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  217. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +59 -0
  218. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +35 -0
  219. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  220. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  221. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  222. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +29 -0
  223. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +44 -0
  224. data/spec/unit/mongoid/extensions/objectid/conversions_spec.rb +22 -0
  225. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  226. data/spec/unit/mongoid/extensions/set/conversions_spec.rb +21 -0
  227. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +28 -0
  228. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  229. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +107 -0
  230. data/spec/unit/mongoid/extensions/time_conversions_spec.rb +186 -0
  231. data/spec/unit/mongoid/extensions/true_class/equality_spec.rb +35 -0
  232. data/spec/unit/mongoid/extras_spec.rb +102 -0
  233. data/spec/unit/mongoid/factory_spec.rb +31 -0
  234. data/spec/unit/mongoid/field_spec.rb +169 -0
  235. data/spec/unit/mongoid/fields_spec.rb +181 -0
  236. data/spec/unit/mongoid/finders_spec.rb +439 -0
  237. data/spec/unit/mongoid/hierarchy_spec.rb +68 -0
  238. data/spec/unit/mongoid/identity_spec.rb +109 -0
  239. data/spec/unit/mongoid/indexes_spec.rb +99 -0
  240. data/spec/unit/mongoid/javascript_spec.rb +48 -0
  241. data/spec/unit/mongoid/logger_spec.rb +38 -0
  242. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  243. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  244. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  245. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  246. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  247. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  248. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  249. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  250. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  251. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  252. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  253. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  254. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  255. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  256. data/spec/unit/mongoid/paranoia_spec.rb +108 -0
  257. data/spec/unit/mongoid/paths_spec.rb +272 -0
  258. data/spec/unit/mongoid/persistence/insert_embedded_spec.rb +154 -0
  259. data/spec/unit/mongoid/persistence/insert_spec.rb +144 -0
  260. data/spec/unit/mongoid/persistence/remove_all_spec.rb +82 -0
  261. data/spec/unit/mongoid/persistence/remove_embedded_spec.rb +152 -0
  262. data/spec/unit/mongoid/persistence/remove_spec.rb +89 -0
  263. data/spec/unit/mongoid/persistence/update_spec.rb +177 -0
  264. data/spec/unit/mongoid/persistence_spec.rb +452 -0
  265. data/spec/unit/mongoid/scope_spec.rb +240 -0
  266. data/spec/unit/mongoid/serialization_spec.rb +43 -0
  267. data/spec/unit/mongoid/state_spec.rb +94 -0
  268. data/spec/unit/mongoid/timestamps_spec.rb +30 -0
  269. data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
  270. data/spec/unit/mongoid/validations/uniqueness_spec.rb +201 -0
  271. data/spec/unit/mongoid/validations_spec.rb +43 -0
  272. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  273. data/spec/unit/mongoid_spec.rb +46 -0
  274. metadata +433 -0
@@ -0,0 +1,7 @@
1
+ class Pet
2
+ include Mongoid::Document
3
+ field :name
4
+ field :weight, :type => Float, :default => 0.0
5
+ embeds_many :vet_visits
6
+ embedded_in :pet_owner, :inverse_of => :pet
7
+ end
@@ -0,0 +1,6 @@
1
+ class PetOwner
2
+ include Mongoid::Document
3
+ field :title
4
+ embeds_one :pet
5
+ embeds_one :address
6
+ end
@@ -0,0 +1,7 @@
1
+ class Phone
2
+ include Mongoid::Document
3
+ field :number
4
+ key :number
5
+ embeds_one :country_code
6
+ embedded_in :person, :inverse_of => :phone_numbers
7
+ end
@@ -0,0 +1,25 @@
1
+ class Tag
2
+ include Mongoid::Document
3
+ field :text
4
+ referenced_in :post, :stored_as => :array
5
+ end
6
+
7
+ class Post
8
+ include Mongoid::Document
9
+ include Mongoid::Versioning
10
+ include Mongoid::Timestamps
11
+ field :title
12
+ referenced_in :person
13
+ referenced_in :author, :foreign_key => :author_id, :class_name => "User"
14
+ referenced_in :poster, :foreign_key => :poster_id, :class_name => "Agent"
15
+
16
+ references_many :tags, :stored_as => :array
17
+
18
+ named_scope :recent, where(:created_at => { "$lt" => Time.now, "$gt" => 30.days.ago })
19
+
20
+ class << self
21
+ def old
22
+ where(:created_at => { "$lt" => 30.days.ago })
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ class Preference
2
+ include Mongoid::Document
3
+ field :name
4
+ field :value
5
+ references_many :people, :stored_as => :array, :inverse_of => :preferences
6
+ validates_length_of :name, :minimum => 2, :allow_nil => true
7
+ end
@@ -0,0 +1,8 @@
1
+ class Question
2
+ include Mongoid::Document
3
+ field :content
4
+ embedded_in :survey, :inverse_of => :questions
5
+ embeds_many :answers
6
+
7
+ accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
8
+ end
@@ -0,0 +1,6 @@
1
+ class Survey
2
+ include Mongoid::Document
3
+ embeds_many :questions
4
+
5
+ accepts_nested_attributes_for :questions, :reject_if => lambda{ |a| a[:content].blank? }, :allow_destroy => true
6
+ end
@@ -0,0 +1,5 @@
1
+ class Translation
2
+ include Mongoid::Document
3
+ field :language
4
+ embedded_in :name, :inverse_of => :translations
5
+ end
@@ -0,0 +1,6 @@
1
+ class User
2
+ include Mongoid::Document
3
+ references_one :account, :foreign_key => :creator_id
4
+ references_many :posts, :foreign_key => :author_id, :inverse_of => :author
5
+ field :name
6
+ end
@@ -0,0 +1,5 @@
1
+ class UserAccount
2
+ include Mongoid::Document
3
+ field :username
4
+ validates_uniqueness_of :username, :message => "is not unique"
5
+ end
@@ -0,0 +1,5 @@
1
+ class VetVisit
2
+ include Mongoid::Document
3
+ field :date, :type => Date
4
+ embedded_in :pet, :inverse_of => :vet_visits
5
+ end
@@ -0,0 +1,5 @@
1
+ class Video
2
+ include Mongoid::Document
3
+ field :title
4
+ embedded_in :person, :inverse_of => :videos
5
+ end
@@ -0,0 +1,33 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ MODELS = File.join(File.dirname(__FILE__), "models")
5
+ $LOAD_PATH.unshift(MODELS)
6
+
7
+ require 'rubygems'
8
+
9
+ gem "mocha", ">= 0.9.8"
10
+
11
+ require "mongoid"
12
+ require "mocha"
13
+ require "rspec"
14
+
15
+ Mongoid.configure do |config|
16
+ name = "mongoid_test"
17
+ host = "localhost"
18
+ config.master = Mongo::Connection.new.db(name)
19
+ config.logger = nil
20
+ # config.slaves = [
21
+ # Mongo::Connection.new(host, 27018, :slave_ok => true).db(name)
22
+ # ]
23
+ end
24
+
25
+ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
26
+
27
+ Rspec.configure do |config|
28
+ config.mock_with :mocha
29
+ config.after :suite do
30
+ Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
31
+ end
32
+ end
33
+
@@ -0,0 +1,193 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Associations::EmbeddedIn do
4
+
5
+ let(:child) do
6
+ Name.new(:first_name => "Drexel", :last_name => "Spivey")
7
+ end
8
+
9
+ let(:target) do
10
+ Person.new(:title => "Pimp")
11
+ end
12
+
13
+ let(:options) do
14
+ Mongoid::Associations::Options.new(:name => :person, :inverse_of => :name)
15
+ end
16
+
17
+ let(:has_many_options) do
18
+ Mongoid::Associations::Options.new(:name => :person, :inverse_of => :addresses)
19
+ end
20
+
21
+ describe "#find" do
22
+
23
+ before do
24
+ @association = Mongoid::Associations::EmbeddedIn.new(target, options)
25
+ end
26
+
27
+ context "when finding by id" do
28
+
29
+ it "always returns the target document" do
30
+ @association.find("").should == target
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ describe "#initialize" do
38
+
39
+ before do
40
+ @association = Mongoid::Associations::EmbeddedIn.new(target, options)
41
+ end
42
+
43
+ it "sets the target" do
44
+ @association.target.should == target
45
+ end
46
+
47
+ it "sets the options" do
48
+ @association.options.should == options
49
+ end
50
+
51
+ end
52
+
53
+ describe "#initialize" do
54
+
55
+ before do
56
+ @parent = Person.new(:title => "Dr")
57
+ @name = Name.new(:first_name => "Richard", :last_name => "Dawkins")
58
+ @parent.name = @name
59
+ @block = Proc.new {
60
+ def extension
61
+ "Testing"
62
+ end
63
+ }
64
+ @options = Mongoid::Associations::Options.new(:name => :person, :extend => @block)
65
+ @association = Mongoid::Associations::EmbeddedIn.new(@parent, @options)
66
+ end
67
+
68
+ context "when the options have an extension" do
69
+
70
+ it "adds the extension module" do
71
+ @association.extension.should == "Testing"
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ describe ".instantiate" do
79
+
80
+ context "when parent exists" do
81
+
82
+ before do
83
+ @parent = stub
84
+ @target = stub(:_parent => @parent)
85
+ @association = Mongoid::Associations::EmbeddedIn.instantiate(@target, options)
86
+ end
87
+
88
+ it "sets the parent to the target" do
89
+ @association.target.should == @parent
90
+ end
91
+
92
+ end
93
+
94
+ context "when parent is nil" do
95
+
96
+ before do
97
+ @document = stub(:_parent => nil)
98
+ end
99
+
100
+ it "returns nil" do
101
+ Mongoid::Associations::EmbeddedIn.instantiate(@document, options).should be_nil
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+
108
+ describe ".macro" do
109
+
110
+ it "returns :embedded_in" do
111
+ Mongoid::Associations::EmbeddedIn.macro.should == :embedded_in
112
+ end
113
+
114
+ end
115
+
116
+ describe "#method_missing" do
117
+
118
+ before do
119
+ @association = Mongoid::Associations::EmbeddedIn.new(target, options)
120
+ end
121
+
122
+ context "when method is a getter" do
123
+
124
+ it "delegates to the target" do
125
+ @association.title.should == "Pimp"
126
+ end
127
+
128
+ end
129
+
130
+ context "when method is a setter" do
131
+
132
+ before do
133
+ @association.title = "Dealer"
134
+ end
135
+
136
+ it "delegates to the target" do
137
+ @association.title.should == "Dealer"
138
+ end
139
+
140
+ end
141
+
142
+ context "when method does not exist" do
143
+
144
+ it "raises an error" do
145
+ lambda { @association.nothing }.should raise_error(NoMethodError)
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+ describe ".update" do
153
+
154
+ context "when child is a has one" do
155
+
156
+ before do
157
+ @name = Name.new(:first_name => "Test", :last_name => "User")
158
+ @person = Person.new(:title => "Mrs")
159
+ @association = Mongoid::Associations::EmbeddedIn.update(@person, @name, options)
160
+ end
161
+
162
+ it "updates the parent document" do
163
+ @person.name.should == @name
164
+ end
165
+
166
+ it "updates the parent attributes" do
167
+ @person.attributes[:name].except(:_id).should ==
168
+ { "first_name" => "Test", "last_name" => "User" }
169
+ end
170
+
171
+ it "returns the proxy association" do
172
+ @association.target.should == @person
173
+ end
174
+
175
+ end
176
+
177
+ context "when child is a has many" do
178
+
179
+ before do
180
+ @address = Address.new(:street => "Broadway")
181
+ @person = Person.new(:title => "Mrs")
182
+ Mongoid::Associations::EmbeddedIn.update(@person, @address, has_many_options)
183
+ end
184
+
185
+ it "updates the parent document" do
186
+ @person.addresses.first.should == @address
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+
193
+ end
@@ -0,0 +1,626 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Associations::EmbedsMany do
4
+
5
+ before do
6
+ @attributes = { "addresses" => [
7
+ { "_id" => "street-1", "street" => "Street 1", "state" => "CA" },
8
+ { "_id" => "street-2", "street" => "Street 2" } ] }
9
+ @document = stub(:raw_attributes => @attributes, :add_observer => true, :observe => true, :update_child => nil)
10
+ end
11
+
12
+ describe "#[]" do
13
+
14
+ before do
15
+ @association = Mongoid::Associations::EmbedsMany.new(
16
+ @document,
17
+ Mongoid::Associations::Options.new(:name => :addresses)
18
+ )
19
+ end
20
+
21
+ context "when the index is present in the association" do
22
+
23
+ it "returns the document at the index" do
24
+ @association[0].should be_a_kind_of(Address)
25
+ @association[0].street.should == "Street 1"
26
+ end
27
+
28
+ end
29
+
30
+ context "when the index is not present in the association" do
31
+
32
+ it "returns nil" do
33
+ @association[3].should be_nil
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ describe "#<<" do
41
+
42
+ before do
43
+ @association = Mongoid::Associations::EmbedsMany.new(
44
+ @document,
45
+ Mongoid::Associations::Options.new(:name => :addresses)
46
+ )
47
+ @address = Address.new
48
+ end
49
+
50
+ it "adds the parent document before appending to the array" do
51
+ @association << @address
52
+ @association.length.should == 3
53
+ @address._parent.should == @document
54
+ end
55
+
56
+ it "allows multiple additions" do
57
+ @association << @address
58
+ @association << @address
59
+ @association.length.should == 4
60
+ end
61
+
62
+ it "sets the index of the document in the array" do
63
+ addr = Address.new
64
+ @association << addr
65
+ addr._index.should == 2
66
+ end
67
+
68
+ end
69
+
70
+ describe "#build" do
71
+
72
+ context "setting the parent relationship" do
73
+
74
+ before do
75
+ @person = Person.new
76
+ end
77
+
78
+ it "happens before any other operation" do
79
+ address = @person.addresses.build(:set_parent => true, :street => "Madison Ave")
80
+ address._parent.should == @person
81
+ @person.addresses.first.should == address
82
+ end
83
+
84
+ end
85
+
86
+ context "when a type is not provided" do
87
+
88
+ before do
89
+ @association = Mongoid::Associations::EmbedsMany.new(
90
+ @document,
91
+ Mongoid::Associations::Options.new(:name => :addresses)
92
+ )
93
+ end
94
+
95
+ it "adds a new document to the array with the supplied parameters" do
96
+ @association.build({ :street => "Street 1" })
97
+ @association.length.should == 3
98
+ @association[2].should be_a_kind_of(Address)
99
+ @association[2].street.should == "Street 1"
100
+ end
101
+
102
+ it "returns the newly built object in the association" do
103
+ address = @association.build({ :street => "Yet Another" })
104
+ address.should be_a_kind_of(Address)
105
+ address.street.should == "Yet Another"
106
+ end
107
+
108
+ end
109
+
110
+ context "when a type is provided" do
111
+
112
+ before do
113
+ @association = Mongoid::Associations::EmbedsMany.new(
114
+ @document,
115
+ Mongoid::Associations::Options.new(:name => :shapes)
116
+ )
117
+ end
118
+
119
+ it "instantiates a class of the type" do
120
+ circle = @association.build({ :radius => 100 }, Circle)
121
+ circle.should be_a_kind_of(Circle)
122
+ circle.radius.should == 100
123
+ end
124
+
125
+ end
126
+
127
+ end
128
+
129
+ context "#count and #size" do
130
+
131
+ before do
132
+ @association = Mongoid::Associations::EmbedsMany.new(
133
+ @document,
134
+ Mongoid::Associations::Options.new(:name => :addresses)
135
+ )
136
+ @association.target.first.new_record = true
137
+ end
138
+
139
+ it "count returns the number of persisted elements" do
140
+ @association.count.should == 1
141
+ end
142
+
143
+ it "size returns the total number of elements" do
144
+ @association.size.should == 2
145
+ end
146
+ end
147
+
148
+ describe "#create" do
149
+
150
+ context "when a type is not provided" do
151
+
152
+ before do
153
+ @association = Mongoid::Associations::EmbedsMany.new(
154
+ @document,
155
+ Mongoid::Associations::Options.new(:name => :addresses)
156
+ )
157
+ @address = mock(:parentize => true, :write_attributes => true, :_index= => true)
158
+ Address.expects(:instantiate).returns(@address)
159
+ end
160
+
161
+ it "builds and saves a new object" do
162
+ @address.expects(:save).returns(true)
163
+ address = @association.create({ :street => "Yet Another" })
164
+ address.should == @address
165
+ end
166
+
167
+ end
168
+
169
+ context "when a type is provided" do
170
+
171
+ before do
172
+ @association = Mongoid::Associations::EmbedsMany.new(
173
+ @document,
174
+ Mongoid::Associations::Options.new(:name => :shapes)
175
+ )
176
+ @circle = mock(:parentize => true, :write_attributes => true, :_index= => true)
177
+ Circle.expects(:instantiate).returns(@circle)
178
+ end
179
+
180
+ it "instantiates a class of that type" do
181
+ @circle.expects(:save).returns(true)
182
+ circle = @association.create({ :radius => 100 }, Circle)
183
+ circle.should == @circle
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+ describe "#create!" do
191
+
192
+ context "when validations pass" do
193
+
194
+ before do
195
+ @association = Mongoid::Associations::EmbedsMany.new(
196
+ @document,
197
+ Mongoid::Associations::Options.new(:name => :addresses)
198
+ )
199
+ @address = mock(:parentize => true, :write_attributes => true, :errors => [], :_index= => true)
200
+ Address.expects(:instantiate).returns(@address)
201
+ end
202
+
203
+ it "builds and saves a new object" do
204
+ @address.expects(:save).returns(true)
205
+ address = @association.create!({ :street => "Yet Another" })
206
+ address.should == @address
207
+ end
208
+ end
209
+
210
+ context "when validations fail" do
211
+
212
+ before do
213
+ @association = Mongoid::Associations::EmbedsMany.new(
214
+ @document,
215
+ Mongoid::Associations::Options.new(:name => :addresses)
216
+ )
217
+ @errors = mock(:full_messages => ["test"], :empty? => false)
218
+ @address = mock(:parentize => true, :write_attributes => true, :_index= => true)
219
+ @address.expects(:errors).twice.returns(@errors)
220
+ Address.expects(:instantiate).returns(@address)
221
+ end
222
+
223
+ it "builds and saves a new object" do
224
+ @address.expects(:save).returns(false)
225
+ lambda {
226
+ @association.create!({ :street => "Yet Another" })
227
+ }.should raise_error(Mongoid::Errors::Validations)
228
+ end
229
+ end
230
+ end
231
+
232
+ describe "#concat" do
233
+
234
+ before do
235
+ @association = Mongoid::Associations::EmbedsMany.new(
236
+ @document,
237
+ Mongoid::Associations::Options.new(:name => :addresses)
238
+ )
239
+ @address = Address.new
240
+ end
241
+
242
+ it "adds the parent document before appending to the array" do
243
+ @association.concat [@address]
244
+ @association.length.should == 3
245
+ @address._parent.should == @document
246
+ end
247
+
248
+ end
249
+
250
+ describe "#clear" do
251
+
252
+ before do
253
+ @association = Mongoid::Associations::EmbedsMany.new(
254
+ @document,
255
+ Mongoid::Associations::Options.new(:name => :addresses)
256
+ )
257
+ @address = Address.new
258
+ @association << @address
259
+ end
260
+
261
+ it "clears out the association" do
262
+ @association.clear
263
+ @association.size.should == 0
264
+ end
265
+
266
+ end
267
+
268
+ describe "#delete_all" do
269
+
270
+ before do
271
+ @association = Mongoid::Associations::EmbedsMany.new(
272
+ @document,
273
+ Mongoid::Associations::Options.new(:name => :addresses)
274
+ )
275
+ @association.clear
276
+ @address = Address.instantiate(:street => "Street 1")
277
+ @association << @address
278
+ end
279
+
280
+ it "aliases to clear" do
281
+ @address.expects(:delete)
282
+ @association.delete_all
283
+ @association.size.should == 0
284
+ end
285
+
286
+ it "returns the number of documents deleted" do
287
+ @address.expects(:delete)
288
+ @association.delete_all.should == 1
289
+ end
290
+
291
+ context "when conditions passed" do
292
+
293
+ it "deletes the correct documents" do
294
+ @address.expects(:delete)
295
+ @association.delete_all(:conditions => { :street => "Street 1" }).should == 1
296
+ @association.size.should == 0
297
+ end
298
+ end
299
+ end
300
+
301
+ describe "#destroy_all" do
302
+
303
+ before do
304
+ @association = Mongoid::Associations::EmbedsMany.new(
305
+ @document,
306
+ Mongoid::Associations::Options.new(:name => :addresses)
307
+ )
308
+ @association.clear
309
+ @address = Address.instantiate(:id => "1", :street => "Street 1")
310
+ @association << @address
311
+ end
312
+
313
+ it "aliases to clear" do
314
+ @address.expects(:destroy)
315
+ @association.destroy_all
316
+ @association.size.should == 0
317
+ end
318
+
319
+ it "returns the number of documents deleted" do
320
+ @address.expects(:destroy)
321
+ @association.destroy_all.should == 1
322
+ end
323
+
324
+ context "when conditions passed" do
325
+
326
+ it "deletes the correct documents" do
327
+ @address.expects(:destroy)
328
+ @association.destroy_all(:conditions => { :street => "Street 1" }).should == 1
329
+ @association.size.should == 0
330
+ end
331
+ end
332
+ end
333
+
334
+ describe "#find" do
335
+
336
+ before do
337
+ @association = Mongoid::Associations::EmbedsMany.new(
338
+ @document,
339
+ Mongoid::Associations::Options.new(:name => :addresses)
340
+ )
341
+ end
342
+
343
+ context "when finding all" do
344
+
345
+ it "returns all the documents" do
346
+ @association.find(:all).should == @association
347
+ end
348
+
349
+ end
350
+
351
+ context "when finding by id" do
352
+
353
+ it "returns the document in the array with that id" do
354
+ address = @association.find("street-2")
355
+ address.should_not be_nil
356
+ end
357
+
358
+ end
359
+
360
+ end
361
+
362
+ describe "#first" do
363
+
364
+ context "when there are elements in the array" do
365
+
366
+ before do
367
+ @association = Mongoid::Associations::EmbedsMany.new(
368
+ @document,
369
+ Mongoid::Associations::Options.new(:name => :addresses)
370
+ )
371
+ end
372
+
373
+ it "returns the first element" do
374
+ @association.first.should be_a_kind_of(Address)
375
+ @association.first.street.should == "Street 1"
376
+ end
377
+
378
+ end
379
+
380
+ context "when the array is empty" do
381
+
382
+ before do
383
+ @association = Mongoid::Associations::EmbedsMany.new(
384
+ Person.new,
385
+ Mongoid::Associations::Options.new(:name => :addresses)
386
+ )
387
+ end
388
+
389
+ it "returns nil" do
390
+ @association.first.should be_nil
391
+ end
392
+
393
+ end
394
+
395
+ end
396
+
397
+ describe "#initialize" do
398
+
399
+ context "setting position" do
400
+
401
+ before do
402
+ @canvas = stub(:raw_attributes => { "shapes" => [{ "_type" => "Circle", "radius" => 5 }] }, :observe => true)
403
+ @association = Mongoid::Associations::EmbedsMany.new(
404
+ @canvas,
405
+ Mongoid::Associations::Options.new(:name => :shapes)
406
+ )
407
+ end
408
+
409
+ it "sets the index of each document" do
410
+ @association.first._index.should == 0
411
+ end
412
+ end
413
+
414
+ context "when no extension exists" do
415
+
416
+ before do
417
+ @canvas = stub(:raw_attributes => { "shapes" => [{ "_type" => "Circle", "radius" => 5 }] }, :observe => true)
418
+ @association = Mongoid::Associations::EmbedsMany.new(
419
+ @canvas,
420
+ Mongoid::Associations::Options.new(:name => :shapes)
421
+ )
422
+ end
423
+
424
+ it "creates the classes based on their types" do
425
+ circle = @association.first
426
+ circle.should be_a_kind_of(Circle)
427
+ circle.radius.should == 5
428
+ end
429
+
430
+ end
431
+
432
+ context "when an extension is in the options" do
433
+
434
+ before do
435
+ @person = Person.new
436
+ @block = Proc.new do
437
+ def extension
438
+ "Testing"
439
+ end
440
+ end
441
+ @association = Mongoid::Associations::EmbedsMany.new(
442
+ @person,
443
+ Mongoid::Associations::Options.new(:name => :addresses, :extend => @block)
444
+ )
445
+ end
446
+
447
+ it "adds the extension module" do
448
+ @association.extension.should == "Testing"
449
+ end
450
+
451
+ end
452
+
453
+ end
454
+
455
+ describe ".instantiate" do
456
+
457
+ it "delegates to new" do
458
+ Mongoid::Associations::EmbedsMany.expects(:new).with(@document, @options, nil)
459
+ Mongoid::Associations::EmbedsMany.instantiate(@document, @options)
460
+ end
461
+
462
+ end
463
+
464
+ describe "#length" do
465
+
466
+ context "#length" do
467
+
468
+ it "returns the length of the delegated array" do
469
+ @association = Mongoid::Associations::EmbedsMany.new(
470
+ @document,
471
+ Mongoid::Associations::Options.new(:name => :addresses)
472
+ )
473
+ @association.length.should == 2
474
+ end
475
+
476
+ end
477
+
478
+ end
479
+
480
+ describe ".macro" do
481
+
482
+ it "returns :embeds_many" do
483
+ Mongoid::Associations::EmbedsMany.macro.should == :embeds_many
484
+ end
485
+
486
+ end
487
+
488
+ describe "#nested_build" do
489
+
490
+ before do
491
+ @association = Mongoid::Associations::EmbedsMany.new(
492
+ @document,
493
+ Mongoid::Associations::Options.new(:name => :addresses)
494
+ )
495
+ end
496
+
497
+ it "should update existing documents" do
498
+ @association.nested_build({ "0" => { :street => "Yet Another" } })
499
+ @association.size.should == 2
500
+ @association[0].street.should == "Yet Another"
501
+ end
502
+
503
+ it "should create new documents" do
504
+ @association.nested_build({ "2" => { :street => "Yet Another" } })
505
+ @association.size.should == 3
506
+ @association[2].street.should == "Yet Another"
507
+ end
508
+
509
+ end
510
+
511
+ describe "#method_missing" do
512
+
513
+ context "when the association class has a criteria class method" do
514
+
515
+ before do
516
+ @association = Mongoid::Associations::EmbedsMany.new(
517
+ @document,
518
+ Mongoid::Associations::Options.new(:name => :addresses)
519
+ )
520
+ end
521
+
522
+ it "returns the criteria" do
523
+ @association.california.should be_a_kind_of(Mongoid::Criteria)
524
+ end
525
+
526
+ it "sets the documents on the criteria" do
527
+ criteria = @association.california
528
+ criteria.documents.should == @association.entries
529
+ end
530
+
531
+ it "returns the scoped documents" do
532
+ addresses = @association.california
533
+ addresses.size.should == 1
534
+ addresses.first.should be_a_kind_of(Address)
535
+ addresses.first.state.should == "CA"
536
+ end
537
+
538
+ end
539
+
540
+ context "when no class method exists" do
541
+
542
+ before do
543
+ @association = Mongoid::Associations::EmbedsMany.new(
544
+ @document,
545
+ Mongoid::Associations::Options.new(:name => :addresses)
546
+ )
547
+ end
548
+
549
+ it "delegates to the array" do
550
+ @association.entries.size.should == 2
551
+ end
552
+
553
+ end
554
+
555
+ end
556
+
557
+ describe "#paginate" do
558
+
559
+ before do
560
+ @association = Mongoid::Associations::EmbedsMany.new(
561
+ @document,
562
+ Mongoid::Associations::Options.new(:name => :addresses)
563
+ )
564
+ @options = { :page => 1, :per_page => 10 }
565
+ @criteria = mock
566
+ end
567
+
568
+ it "creates a criteria and paginates it" do
569
+ Mongoid::Criteria.expects(:translate).with(Address, @options).returns(@criteria)
570
+ @criteria.expects(:documents=).with(@association.target)
571
+ @criteria.expects(:paginate).returns([])
572
+ @association.paginate(@options).should == []
573
+ end
574
+ end
575
+
576
+ describe "#push" do
577
+
578
+ before do
579
+ @association = Mongoid::Associations::EmbedsMany.new(
580
+ @document,
581
+ Mongoid::Associations::Options.new(:name => :addresses)
582
+ )
583
+ @address = Address.new
584
+ end
585
+
586
+ it "adds the parent document before appending to the array" do
587
+ @association.push @address
588
+ @association.length.should == 3
589
+ @address._parent.should == @document
590
+ end
591
+
592
+ it "appends the document to the end of the array" do
593
+ @association.push(Address.new)
594
+ @association.length.should == 3
595
+ end
596
+
597
+ end
598
+
599
+ describe ".update" do
600
+
601
+ before do
602
+ @address = Address.new(:street => "Madison Ave")
603
+ @person = Person.new(:title => "Sir")
604
+ @association = Mongoid::Associations::EmbedsMany.update(
605
+ [@address],
606
+ @person,
607
+ Mongoid::Associations::Options.new(:name => :addresses)
608
+ )
609
+ end
610
+
611
+ it "parentizes the child document" do
612
+ @address._parent.should == @person
613
+ end
614
+
615
+ it "sets the attributes of the child on the parent" do
616
+ @person.attributes[:addresses].should ==
617
+ [{ "_id" => "madison-ave", "street" => "Madison Ave" }]
618
+ end
619
+
620
+ it "returns the association proxy" do
621
+ @association.target.size.should == 1
622
+ end
623
+
624
+ end
625
+
626
+ end