PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/dm-constraints/spec/integration/constraints_spec.rb

https://github.com/gyngve/dm-more
Ruby | 342 lines | 268 code | 63 blank | 11 comment | 24 complexity | 61b281e803202c199ce25f616a59a3c5 MD5 | raw file
  1. require 'pathname'
  2. require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
  3. ADAPTERS.each do |adapter|
  4. describe 'DataMapper::Constraints' do
  5. # load_models_for_metaphor :stable, :farmer, :cow
  6. before do
  7. DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[adapter]
  8. class ::Stable
  9. include DataMapper::Resource
  10. include DataMapper::Constraints
  11. property :id, Serial
  12. property :location, String
  13. property :size, Integer
  14. has n, :cows
  15. end
  16. class ::Farmer
  17. include DataMapper::Resource
  18. include DataMapper::Constraints
  19. property :first_name, String, :key => true
  20. property :last_name, String, :key => true
  21. has n, :cows
  22. end
  23. class ::Cow
  24. include DataMapper::Resource
  25. include DataMapper::Constraints
  26. property :id, Serial
  27. property :name, String
  28. property :breed, String
  29. belongs_to :stable
  30. belongs_to :farmer
  31. end
  32. #Used to test a belongs_to association with no has() association
  33. #on the other end
  34. class ::Pig
  35. include DataMapper::Resource
  36. include DataMapper::Constraints
  37. property :id, Serial
  38. property :name, String
  39. belongs_to :farmer
  40. end
  41. DataMapper.auto_migrate!
  42. end
  43. it "is included when DataMapper::Constraints is loaded" do
  44. Cow.new.should be_kind_of(DataMapper::Constraints)
  45. end
  46. it "should be able to create related objects with a foreign key constraint" do
  47. @s = Stable.create(:location => "Hometown")
  48. @c1 = Cow.create(:name => "Bea", :stable => @s)
  49. end
  50. it "should be able to create related objects with a composite foreign key constraint" do
  51. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  52. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  53. end
  54. it "should not be able to create related objects with a failing foreign key constraint" do
  55. s = Stable.create
  56. lambda { @c1 = Cow.create(:name => "Bea", :stable_id => s.id + 1) }.should raise_error
  57. end
  58. # :constraint associations
  59. # value | on deletion of parent...
  60. # ---------------------------------
  61. # :protect | raises exception if there are child records
  62. # :destroy | deletes children
  63. # :destroy! | deletes children directly without instantiating the resource, bypassing any hooks
  64. # :set_nil | sets parent id to nil in child associations
  65. # :skip | does not do anything with children (they'll become orphan records)
  66. describe "constraint options" do
  67. describe "when no constraint options are given" do
  68. it "should destroy the parent if there are no children in the association" do
  69. @f1 = Farmer.create(:first_name => "John", :last_name => "Doe")
  70. @f2 = Farmer.create(:first_name => "Some", :last_name => "Body")
  71. @c1 = Cow.create(:name => "Bea", :farmer => @f2)
  72. @f1.destroy.should == true
  73. end
  74. it "should not destroy the parent if there are children in the association" do
  75. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  76. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  77. @f.destroy.should == false
  78. end
  79. end
  80. describe "when :constraint => :protect is given" do
  81. before do
  82. class ::Farmer
  83. has n, :cows, :constraint => :protect
  84. end
  85. class ::Cow
  86. belongs_to :farmer
  87. end
  88. end
  89. it "should destroy the parent if there are no children in the association" do
  90. @f1 = Farmer.create(:first_name => "John", :last_name => "Doe")
  91. @f2 = Farmer.create(:first_name => "Some", :last_name => "Body")
  92. @c1 = Cow.create(:name => "Bea", :farmer => @f2)
  93. @f1.destroy.should == true
  94. end
  95. it "should not destroy the parent if there are children in the association" do
  96. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  97. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  98. @f.destroy.should == false
  99. end
  100. it "the child should be destroyable" do
  101. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  102. @c = Cow.create(:name => "Bea", :farmer => @f)
  103. @c.destroy.should == true
  104. end
  105. end
  106. describe "when :constraint => :destroy is given" do
  107. before do
  108. class ::Farmer
  109. has n, :cows, :constraint => :destroy
  110. end
  111. class ::Cow
  112. belongs_to :farmer
  113. end
  114. DataMapper.auto_migrate!
  115. end
  116. describe "on deletion of the parent" do
  117. before(:each) do
  118. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  119. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  120. @c2 = Cow.create(:name => "Riksa", :farmer => @f)
  121. end
  122. it "should let the parent to be destroyed" do
  123. @f.destroy.should == true
  124. @f.should be_new_record
  125. end
  126. it "should destroy the children" do
  127. @f.destroy
  128. @f.cows.all? { |c| c.should be_new_record }
  129. end
  130. end
  131. it "the child should be destroyable" do
  132. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  133. @c = Cow.create(:name => "Bea", :farmer => @f)
  134. @c.destroy.should == true
  135. end
  136. end
  137. describe "when :constraint => :destroy! is given" do
  138. before do
  139. class ::Farmer
  140. has n, :cows, :constraint => :destroy!
  141. end
  142. class ::Cow
  143. belongs_to :farmer
  144. end
  145. DataMapper.auto_migrate!
  146. end
  147. describe "on deletion of the parent" do
  148. before(:each) do
  149. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  150. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  151. @c2 = Cow.create(:name => "Riksa", :farmer => @f)
  152. end
  153. it "should let the parent to be destroyed" do
  154. @f.destroy.should == true
  155. @f.should be_new_record
  156. end
  157. it "should destroy the children" do
  158. @f.destroy
  159. @f.cows.all? { |c| c.should be_new_record }
  160. end
  161. end
  162. it "the child should be destroyable" do
  163. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  164. @c = Cow.create(:name => "Bea", :farmer => @f)
  165. @c.destroy.should == true
  166. end
  167. end
  168. describe "when :constraint => :set_nil is given" do
  169. before do
  170. class ::Farmer
  171. has n, :cows, :constraint => :set_nil
  172. end
  173. class ::Cow
  174. belongs_to :farmer
  175. end
  176. DataMapper.auto_migrate!
  177. end
  178. describe "on deletion of the parent" do
  179. before(:each) do
  180. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  181. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  182. @c2 = Cow.create(:name => "Riksa", :farmer => @f)
  183. end
  184. it "should let the parent to be destroyed" do
  185. @f.destroy.should == true
  186. @f.should be_new_record
  187. end
  188. it "should set the foreign_key ids of children to nil" do
  189. @f.destroy
  190. @f.cows.all? { |c| c.farmer.should be_nil }
  191. end
  192. end
  193. it "the child should be destroyable" do
  194. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  195. @c = Cow.create(:name => "Bea", :farmer => @f)
  196. @c.destroy.should == true
  197. end
  198. end # describe
  199. describe "when :constraint => :skip is given" do
  200. before do
  201. class ::Farmer
  202. has n, :cows, :constraint => :skip
  203. end
  204. class ::Cow
  205. belongs_to :farmer
  206. end
  207. DataMapper.auto_migrate!
  208. end
  209. describe "on deletion of the parent" do
  210. before(:each) do
  211. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  212. @c1 = Cow.create(:name => "Bea", :farmer => @f)
  213. @c2 = Cow.create(:name => "Riksa", :farmer => @f)
  214. end
  215. it "should let the parent to be destroyed" do
  216. @f.destroy.should == true
  217. @f.should be_new_record
  218. end
  219. it "should let the children become orphan records" do
  220. @f.destroy
  221. @c1.farmer.should be_new_record
  222. @c2.farmer.should be_new_record
  223. end
  224. end
  225. it "the child should be destroyable" do
  226. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  227. @c = Cow.create(:name => "Bea", :farmer => @f)
  228. @c.destroy.should == true
  229. end
  230. end # describe
  231. describe "when an invalid option is given" do
  232. before do
  233. end
  234. class ::Farmer
  235. end
  236. it "should raise an error" do
  237. lambda do
  238. class ::Farmer
  239. has n, :cows, :constraint => :chocolate
  240. end
  241. end.should raise_error(ArgumentError)
  242. end
  243. end
  244. end # describe 'constraint options'
  245. describe "belongs_to without matching has association" do
  246. it "should destroy the parent if there are no children in the association" do
  247. @f1 = Farmer.create(:first_name => "John", :last_name => "Doe")
  248. @f2 = Farmer.create(:first_name => "Some", :last_name => "Body")
  249. @p1 = Pig.create(:name => "Bea", :farmer => @f2)
  250. @f1.destroy.should == true
  251. end
  252. case adapter
  253. when :mysql
  254. it "should raise a MysqlError when destroying the parent if there are children in the association" do
  255. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  256. @p1 = Pig.create(:name => "Bea", :farmer => @f)
  257. lambda {@f.destroy}.should raise_error(MysqlError)
  258. end
  259. when :postgres
  260. it "should raise a PostgresError when destroying the parent if there are children in the association" do
  261. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  262. @p1 = Pig.create(:name => "Bea", :farmer => @f)
  263. lambda {@f.destroy}.should raise_error(PostgresError)
  264. end
  265. else
  266. it "should destroy the parent if there are children in the association and the adapter does not support constraints" do
  267. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  268. @p1 = Pig.create(:name => "Bea", :farmer => @f)
  269. @f.destroy.should == true
  270. end
  271. end
  272. it "the child should be destroyable" do
  273. @f = Farmer.create(:first_name => "John", :last_name => "Doe")
  274. @p = Pig.create(:name => "Bea", :farmer => @f)
  275. @p.destroy.should == true
  276. end
  277. end # describe 'belongs_to without matching has association'
  278. end # DataMapper::Constraints
  279. end # ADAPTERS.each