humanoid 1.2.7

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 (210) hide show
  1. data/.gitignore +6 -0
  2. data/.watchr +29 -0
  3. data/HISTORY +342 -0
  4. data/MIT_LICENSE +20 -0
  5. data/README.rdoc +56 -0
  6. data/Rakefile +53 -0
  7. data/VERSION +1 -0
  8. data/caliper.yml +4 -0
  9. data/humanoid.gemspec +374 -0
  10. data/lib/humanoid.rb +111 -0
  11. data/lib/humanoid/associations.rb +258 -0
  12. data/lib/humanoid/associations/belongs_to.rb +64 -0
  13. data/lib/humanoid/associations/belongs_to_related.rb +62 -0
  14. data/lib/humanoid/associations/has_many.rb +180 -0
  15. data/lib/humanoid/associations/has_many_related.rb +109 -0
  16. data/lib/humanoid/associations/has_one.rb +95 -0
  17. data/lib/humanoid/associations/has_one_related.rb +81 -0
  18. data/lib/humanoid/associations/options.rb +57 -0
  19. data/lib/humanoid/associations/proxy.rb +31 -0
  20. data/lib/humanoid/attributes.rb +184 -0
  21. data/lib/humanoid/callbacks.rb +23 -0
  22. data/lib/humanoid/collection.rb +118 -0
  23. data/lib/humanoid/collections/cyclic_iterator.rb +34 -0
  24. data/lib/humanoid/collections/master.rb +28 -0
  25. data/lib/humanoid/collections/mimic.rb +46 -0
  26. data/lib/humanoid/collections/operations.rb +41 -0
  27. data/lib/humanoid/collections/slaves.rb +44 -0
  28. data/lib/humanoid/commands.rb +182 -0
  29. data/lib/humanoid/commands/create.rb +21 -0
  30. data/lib/humanoid/commands/delete.rb +16 -0
  31. data/lib/humanoid/commands/delete_all.rb +23 -0
  32. data/lib/humanoid/commands/deletion.rb +18 -0
  33. data/lib/humanoid/commands/destroy.rb +19 -0
  34. data/lib/humanoid/commands/destroy_all.rb +23 -0
  35. data/lib/humanoid/commands/save.rb +27 -0
  36. data/lib/humanoid/components.rb +24 -0
  37. data/lib/humanoid/config.rb +84 -0
  38. data/lib/humanoid/contexts.rb +25 -0
  39. data/lib/humanoid/contexts/enumerable.rb +117 -0
  40. data/lib/humanoid/contexts/ids.rb +25 -0
  41. data/lib/humanoid/contexts/mongo.rb +224 -0
  42. data/lib/humanoid/contexts/paging.rb +42 -0
  43. data/lib/humanoid/criteria.rb +259 -0
  44. data/lib/humanoid/criterion/complex.rb +21 -0
  45. data/lib/humanoid/criterion/exclusion.rb +65 -0
  46. data/lib/humanoid/criterion/inclusion.rb +91 -0
  47. data/lib/humanoid/criterion/optional.rb +128 -0
  48. data/lib/humanoid/cursor.rb +82 -0
  49. data/lib/humanoid/document.rb +300 -0
  50. data/lib/humanoid/enslavement.rb +38 -0
  51. data/lib/humanoid/errors.rb +77 -0
  52. data/lib/humanoid/extensions.rb +84 -0
  53. data/lib/humanoid/extensions/array/accessors.rb +17 -0
  54. data/lib/humanoid/extensions/array/aliasing.rb +4 -0
  55. data/lib/humanoid/extensions/array/assimilation.rb +26 -0
  56. data/lib/humanoid/extensions/array/conversions.rb +29 -0
  57. data/lib/humanoid/extensions/array/parentization.rb +13 -0
  58. data/lib/humanoid/extensions/boolean/conversions.rb +16 -0
  59. data/lib/humanoid/extensions/date/conversions.rb +15 -0
  60. data/lib/humanoid/extensions/datetime/conversions.rb +17 -0
  61. data/lib/humanoid/extensions/float/conversions.rb +16 -0
  62. data/lib/humanoid/extensions/hash/accessors.rb +38 -0
  63. data/lib/humanoid/extensions/hash/assimilation.rb +30 -0
  64. data/lib/humanoid/extensions/hash/conversions.rb +15 -0
  65. data/lib/humanoid/extensions/hash/criteria_helpers.rb +20 -0
  66. data/lib/humanoid/extensions/hash/scoping.rb +12 -0
  67. data/lib/humanoid/extensions/integer/conversions.rb +16 -0
  68. data/lib/humanoid/extensions/nil/assimilation.rb +13 -0
  69. data/lib/humanoid/extensions/object/conversions.rb +33 -0
  70. data/lib/humanoid/extensions/proc/scoping.rb +12 -0
  71. data/lib/humanoid/extensions/string/conversions.rb +15 -0
  72. data/lib/humanoid/extensions/string/inflections.rb +97 -0
  73. data/lib/humanoid/extensions/symbol/inflections.rb +36 -0
  74. data/lib/humanoid/extensions/time/conversions.rb +18 -0
  75. data/lib/humanoid/factory.rb +19 -0
  76. data/lib/humanoid/field.rb +39 -0
  77. data/lib/humanoid/fields.rb +62 -0
  78. data/lib/humanoid/finders.rb +224 -0
  79. data/lib/humanoid/identity.rb +39 -0
  80. data/lib/humanoid/indexes.rb +30 -0
  81. data/lib/humanoid/matchers.rb +36 -0
  82. data/lib/humanoid/matchers/all.rb +11 -0
  83. data/lib/humanoid/matchers/default.rb +26 -0
  84. data/lib/humanoid/matchers/exists.rb +13 -0
  85. data/lib/humanoid/matchers/gt.rb +11 -0
  86. data/lib/humanoid/matchers/gte.rb +11 -0
  87. data/lib/humanoid/matchers/in.rb +11 -0
  88. data/lib/humanoid/matchers/lt.rb +11 -0
  89. data/lib/humanoid/matchers/lte.rb +11 -0
  90. data/lib/humanoid/matchers/ne.rb +11 -0
  91. data/lib/humanoid/matchers/nin.rb +11 -0
  92. data/lib/humanoid/matchers/size.rb +11 -0
  93. data/lib/humanoid/memoization.rb +27 -0
  94. data/lib/humanoid/named_scope.rb +40 -0
  95. data/lib/humanoid/scope.rb +75 -0
  96. data/lib/humanoid/timestamps.rb +30 -0
  97. data/lib/humanoid/versioning.rb +28 -0
  98. data/perf/benchmark.rb +77 -0
  99. data/spec/integration/humanoid/associations_spec.rb +301 -0
  100. data/spec/integration/humanoid/attributes_spec.rb +22 -0
  101. data/spec/integration/humanoid/commands_spec.rb +216 -0
  102. data/spec/integration/humanoid/contexts/enumerable_spec.rb +33 -0
  103. data/spec/integration/humanoid/criteria_spec.rb +224 -0
  104. data/spec/integration/humanoid/document_spec.rb +587 -0
  105. data/spec/integration/humanoid/extensions_spec.rb +26 -0
  106. data/spec/integration/humanoid/finders_spec.rb +119 -0
  107. data/spec/integration/humanoid/inheritance_spec.rb +137 -0
  108. data/spec/integration/humanoid/named_scope_spec.rb +46 -0
  109. data/spec/models/address.rb +39 -0
  110. data/spec/models/animal.rb +6 -0
  111. data/spec/models/comment.rb +8 -0
  112. data/spec/models/country_code.rb +6 -0
  113. data/spec/models/employer.rb +5 -0
  114. data/spec/models/game.rb +6 -0
  115. data/spec/models/inheritance.rb +56 -0
  116. data/spec/models/location.rb +5 -0
  117. data/spec/models/mixed_drink.rb +4 -0
  118. data/spec/models/name.rb +13 -0
  119. data/spec/models/namespacing.rb +11 -0
  120. data/spec/models/patient.rb +4 -0
  121. data/spec/models/person.rb +98 -0
  122. data/spec/models/pet.rb +7 -0
  123. data/spec/models/pet_owner.rb +6 -0
  124. data/spec/models/phone.rb +7 -0
  125. data/spec/models/post.rb +15 -0
  126. data/spec/models/translation.rb +5 -0
  127. data/spec/models/vet_visit.rb +5 -0
  128. data/spec/spec.opts +3 -0
  129. data/spec/spec_helper.rb +31 -0
  130. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +141 -0
  131. data/spec/unit/mongoid/associations/belongs_to_spec.rb +193 -0
  132. data/spec/unit/mongoid/associations/has_many_related_spec.rb +387 -0
  133. data/spec/unit/mongoid/associations/has_many_spec.rb +471 -0
  134. data/spec/unit/mongoid/associations/has_one_related_spec.rb +179 -0
  135. data/spec/unit/mongoid/associations/has_one_spec.rb +282 -0
  136. data/spec/unit/mongoid/associations/options_spec.rb +191 -0
  137. data/spec/unit/mongoid/associations_spec.rb +545 -0
  138. data/spec/unit/mongoid/attributes_spec.rb +484 -0
  139. data/spec/unit/mongoid/callbacks_spec.rb +55 -0
  140. data/spec/unit/mongoid/collection_spec.rb +171 -0
  141. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  142. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  143. data/spec/unit/mongoid/collections/mimic_spec.rb +43 -0
  144. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  145. data/spec/unit/mongoid/commands/create_spec.rb +30 -0
  146. data/spec/unit/mongoid/commands/delete_all_spec.rb +58 -0
  147. data/spec/unit/mongoid/commands/delete_spec.rb +35 -0
  148. data/spec/unit/mongoid/commands/destroy_all_spec.rb +23 -0
  149. data/spec/unit/mongoid/commands/destroy_spec.rb +44 -0
  150. data/spec/unit/mongoid/commands/save_spec.rb +105 -0
  151. data/spec/unit/mongoid/commands_spec.rb +282 -0
  152. data/spec/unit/mongoid/config_spec.rb +165 -0
  153. data/spec/unit/mongoid/contexts/enumerable_spec.rb +374 -0
  154. data/spec/unit/mongoid/contexts/mongo_spec.rb +505 -0
  155. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  156. data/spec/unit/mongoid/criteria_spec.rb +769 -0
  157. data/spec/unit/mongoid/criterion/complex_spec.rb +19 -0
  158. data/spec/unit/mongoid/criterion/exclusion_spec.rb +91 -0
  159. data/spec/unit/mongoid/criterion/inclusion_spec.rb +211 -0
  160. data/spec/unit/mongoid/criterion/optional_spec.rb +329 -0
  161. data/spec/unit/mongoid/cursor_spec.rb +74 -0
  162. data/spec/unit/mongoid/document_spec.rb +986 -0
  163. data/spec/unit/mongoid/enslavement_spec.rb +63 -0
  164. data/spec/unit/mongoid/errors_spec.rb +103 -0
  165. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  166. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  167. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +35 -0
  168. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  169. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  170. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +102 -0
  171. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +70 -0
  172. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  173. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  174. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +46 -0
  175. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +21 -0
  176. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  177. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  178. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  179. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +24 -0
  180. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +43 -0
  181. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  182. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +17 -0
  183. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  184. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +91 -0
  185. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +70 -0
  186. data/spec/unit/mongoid/factory_spec.rb +31 -0
  187. data/spec/unit/mongoid/field_spec.rb +81 -0
  188. data/spec/unit/mongoid/fields_spec.rb +158 -0
  189. data/spec/unit/mongoid/finders_spec.rb +368 -0
  190. data/spec/unit/mongoid/identity_spec.rb +88 -0
  191. data/spec/unit/mongoid/indexes_spec.rb +93 -0
  192. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  193. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  194. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  195. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  196. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  197. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  198. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  199. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  200. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  201. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  202. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  203. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  204. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  205. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  206. data/spec/unit/mongoid/scope_spec.rb +240 -0
  207. data/spec/unit/mongoid/timestamps_spec.rb +25 -0
  208. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  209. data/spec/unit/mongoid_spec.rb +37 -0
  210. metadata +431 -0
@@ -0,0 +1,5 @@
1
+ class Location
2
+ include Humanoid::Document
3
+ field :name
4
+ belongs_to :address, :inverse_of => :locations
5
+ end
@@ -0,0 +1,4 @@
1
+ class MixedDrink
2
+ include Humanoid::Document
3
+ field :name
4
+ end
@@ -0,0 +1,13 @@
1
+ class Name
2
+ include Humanoid::Document
3
+ field :first_name
4
+ field :last_name
5
+ field :parent_title
6
+ key :first_name, :last_name
7
+ has_many :translations
8
+ belongs_to :person, :inverse_of => :name
9
+
10
+ def set_parent=(set = false)
11
+ self.parent_title = person.title if set
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Medical
2
+ class Patient
3
+ include Humanoid::Document
4
+ field :name
5
+ has_many :prescriptions, :class_name => "Medical::Prescription"
6
+ end
7
+ class Prescription
8
+ include Humanoid::Document
9
+ field :name
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ class Patient
2
+ include Humanoid::Document
3
+ store_in :inpatient
4
+ end
@@ -0,0 +1,98 @@
1
+ class Person
2
+ include Humanoid::Document
3
+ include Humanoid::Timestamps
4
+
5
+ field :title
6
+ field :terms, :type => Boolean
7
+ field :pets, :type => Boolean, :default => false
8
+ field :age, :type => Integer, :default => 100
9
+ field :dob, :type => Date
10
+ field :mixed_drink, :type => MixedDrink
11
+ field :employer_id
12
+ field :lunch_time, :type => Time
13
+ field :aliases, :type => Array
14
+ field :map, :type => Hash
15
+ field :score, :type => Integer
16
+ field :blood_alcohol_content, :type => Float, :default => lambda{ 0.0 }
17
+ field :ssn
18
+
19
+ index :age
20
+ index :addresses
21
+ index :dob
22
+ index :name
23
+ index :title
24
+ index :ssn, :unique => true
25
+
26
+ attr_reader :rescored
27
+
28
+ has_many :addresses do
29
+ def extension
30
+ "Testing"
31
+ end
32
+ def find_by_street(street)
33
+ @target.select { |doc| doc.street == street }
34
+ end
35
+ end
36
+
37
+ has_many :phone_numbers, :class_name => "Phone"
38
+
39
+ has_one :name do
40
+ def extension
41
+ "Testing"
42
+ end
43
+ def dawkins?
44
+ first_name == "Richard" && last_name == "Dawkins"
45
+ end
46
+ end
47
+
48
+ has_one :pet, :class_name => "Animal"
49
+
50
+ accepts_nested_attributes_for :addresses, :reject_if => lambda { |attrs| attrs["street"].blank? }
51
+ accepts_nested_attributes_for :name
52
+
53
+ has_one_related :game do
54
+ def extension
55
+ "Testing"
56
+ end
57
+ end
58
+
59
+ has_many_related :posts do
60
+ def extension
61
+ "Testing"
62
+ end
63
+ end
64
+
65
+ def score_with_rescoring=(score)
66
+ @rescored = score.to_i + 20
67
+ self.score_without_rescoring = score
68
+ end
69
+
70
+ alias_method_chain :score=, :rescoring
71
+
72
+ def update_addresses
73
+ addresses.each do |address|
74
+ address.street = "Updated Address"
75
+ end
76
+ end
77
+
78
+ def employer=(emp)
79
+ self.employer_id = emp.id
80
+ end
81
+
82
+ class << self
83
+ def accepted
84
+ criteria.where(:terms => true)
85
+ end
86
+ def knight
87
+ criteria.where(:title => "Sir")
88
+ end
89
+ def old
90
+ criteria.where(:age => { "$gt" => 50 })
91
+ end
92
+ end
93
+
94
+ end
95
+
96
+ class Doctor < Person
97
+ field :specialty
98
+ end
@@ -0,0 +1,7 @@
1
+ class Pet
2
+ include Humanoid::Document
3
+ field :name
4
+ field :weight, :type => Float, :default => 0.0
5
+ has_many :vet_visits
6
+ belongs_to :pet_owner, :inverse_of => :pet
7
+ end
@@ -0,0 +1,6 @@
1
+ class PetOwner
2
+ include Humanoid::Document
3
+ field :title
4
+ has_one :pet
5
+ has_one :address
6
+ end
@@ -0,0 +1,7 @@
1
+ class Phone
2
+ include Humanoid::Document
3
+ field :number
4
+ key :number
5
+ belongs_to :person, :inverse_of => :phone_numbers
6
+ has_one :country_code
7
+ end
@@ -0,0 +1,15 @@
1
+ class Post
2
+ include Humanoid::Document
3
+ include Humanoid::Versioning
4
+ include Humanoid::Timestamps
5
+ field :title
6
+ belongs_to_related :person
7
+
8
+ named_scope :recent, where(:created_at => { "$lt" => Time.now, "$gt" => 30.days.ago })
9
+
10
+ class << self
11
+ def old
12
+ where(:created_at => { "$lt" => 30.days.ago })
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class Translation
2
+ include Humanoid::Document
3
+ field :language
4
+ belongs_to :name, :inverse_of => :translations
5
+ end
@@ -0,0 +1,5 @@
1
+ class VetVisit
2
+ include Humanoid::Document
3
+ field :date, :type => Date
4
+ belongs_to :pet, :inverse_of => :vet_visits
5
+ end
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format nested
3
+ --drb
@@ -0,0 +1,31 @@
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 "mocha"
12
+ require "mongoid"
13
+ require "spec"
14
+
15
+ Mongoid.configure do |config|
16
+ name = "mongoid_test"
17
+ host = "localhost"
18
+ config.master = Mongo::Connection.new.db(name)
19
+ # config.slaves = [
20
+ # Mongo::Connection.new(host, 27018, :slave_ok => true).db(name)
21
+ # ]
22
+ end
23
+
24
+ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
25
+
26
+ Spec::Runner.configure do |config|
27
+ config.mock_with :mocha
28
+ config.after :suite do
29
+ Mongoid.master.collections.each(&:drop)
30
+ end
31
+ end
@@ -0,0 +1,141 @@
1
+ require "spec_helper"
2
+
3
+ describe Humanoid::Associations::BelongsToRelated do
4
+
5
+ describe ".initialize" do
6
+
7
+ context "when related id has been set" do
8
+
9
+ before do
10
+ @document = stub(:person_id => "5")
11
+ @options = Humanoid::Associations::Options.new(:name => :person)
12
+ @related = stub
13
+ end
14
+
15
+ it "finds the object by id" do
16
+ Person.expects(:find).with(@document.person_id).returns(@related)
17
+ association = Humanoid::Associations::BelongsToRelated.new(@document, "5", @options)
18
+ association.should == @related
19
+ end
20
+
21
+ end
22
+
23
+ context "when options have an extension" do
24
+
25
+ before do
26
+ @document = stub(:person_id => "5")
27
+ @block = Proc.new {
28
+ def extension
29
+ "Testing"
30
+ end
31
+ }
32
+ @options = Humanoid::Associations::Options.new(:name => :person, :extend => @block)
33
+ @related = stub
34
+ Person.expects(:find).with(@document.person_id).returns(@related)
35
+ @association = Humanoid::Associations::BelongsToRelated.new(@document, "5", @options)
36
+ end
37
+
38
+ it "adds the extension module" do
39
+ @association.extension.should == "Testing"
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ describe ".instantiate" do
47
+
48
+ context "when foreign key is not nil" do
49
+
50
+ before do
51
+ @document = stub(:person_id => "5")
52
+ @options = Humanoid::Associations::Options.new(:name => :person)
53
+ end
54
+
55
+ it "delegates to new" do
56
+ Humanoid::Associations::BelongsToRelated.expects(:new).with(@document, "5", @options, nil)
57
+ Humanoid::Associations::BelongsToRelated.instantiate(@document, @options)
58
+ end
59
+
60
+ end
61
+
62
+ context "when foreign key is nil" do
63
+
64
+ before do
65
+ @document = stub(:person_id => nil)
66
+ @options = Humanoid::Associations::Options.new(:name => :person)
67
+ end
68
+
69
+ it "returns nil" do
70
+ Humanoid::Associations::BelongsToRelated.instantiate(@document, @options).should be_nil
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ describe "#method_missing" do
78
+
79
+ before do
80
+ @person = Person.new(:title => "Mr")
81
+ @document = stub(:person_id => "5")
82
+ @options = Humanoid::Associations::Options.new(:name => :person)
83
+ Person.expects(:find).with(@document.person_id).returns(@person)
84
+ @association = Humanoid::Associations::BelongsToRelated.new(@document, "5", @options)
85
+ end
86
+
87
+ context "when getting values" do
88
+
89
+ it "delegates to the document" do
90
+ @association.title.should == "Mr"
91
+ end
92
+
93
+ end
94
+
95
+ context "when setting values" do
96
+
97
+ it "delegates to the document" do
98
+ @association.title = "Sir"
99
+ @association.title.should == "Sir"
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+ describe ".macro" do
107
+
108
+ it "returns :belongs_to_related" do
109
+ Humanoid::Associations::BelongsToRelated.macro.should == :belongs_to_related
110
+ end
111
+
112
+ end
113
+
114
+ describe ".update" do
115
+
116
+ before do
117
+ @related = stub(:id => "5")
118
+ @child = Game.new
119
+ @options = Humanoid::Associations::Options.new(:name => :person)
120
+ @association = Humanoid::Associations::BelongsToRelated.update(@related, @child, @options)
121
+ end
122
+
123
+ it "sets the related object id on the parent" do
124
+ @child.person_id.should == "5"
125
+ end
126
+
127
+ it "returns the proxy" do
128
+ @association.target.should == @related
129
+ end
130
+
131
+ context "when target is nil" do
132
+
133
+ it "returns nil" do
134
+ Humanoid::Associations::BelongsToRelated.update(nil, @child, @options).should be_nil
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,193 @@
1
+ require "spec_helper"
2
+
3
+ describe Humanoid::Associations::BelongsTo 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
+ Humanoid::Associations::Options.new(:name => :person, :inverse_of => :name)
15
+ end
16
+
17
+ let(:has_many_options) do
18
+ Humanoid::Associations::Options.new(:name => :person, :inverse_of => :addresses)
19
+ end
20
+
21
+ describe "#find" do
22
+
23
+ before do
24
+ @association = Humanoid::Associations::BelongsTo.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 = Humanoid::Associations::BelongsTo.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 = Humanoid::Associations::Options.new(:name => :person, :extend => @block)
65
+ @association = Humanoid::Associations::BelongsTo.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 = Humanoid::Associations::BelongsTo.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
+ Humanoid::Associations::BelongsTo.instantiate(@document, options).should be_nil
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+
108
+ describe ".macro" do
109
+
110
+ it "returns :belongs_to" do
111
+ Humanoid::Associations::BelongsTo.macro.should == :belongs_to
112
+ end
113
+
114
+ end
115
+
116
+ describe "#method_missing" do
117
+
118
+ before do
119
+ @association = Humanoid::Associations::BelongsTo.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 = Humanoid::Associations::BelongsTo.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", "_type" => "Name" }
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
+ Humanoid::Associations::BelongsTo.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