sbf-dm-core 1.3.0.beta

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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +29 -0
  3. data/.document +5 -0
  4. data/.gitignore +44 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +468 -0
  7. data/.travis.yml +57 -0
  8. data/.yardopts +1 -0
  9. data/Gemfile +70 -0
  10. data/LICENSE +20 -0
  11. data/README.md +269 -0
  12. data/Rakefile +4 -0
  13. data/dm-core.gemspec +21 -0
  14. data/lib/dm-core/adapters/abstract_adapter.rb +233 -0
  15. data/lib/dm-core/adapters/in_memory_adapter.rb +110 -0
  16. data/lib/dm-core/adapters.rb +249 -0
  17. data/lib/dm-core/associations/many_to_many.rb +477 -0
  18. data/lib/dm-core/associations/many_to_one.rb +282 -0
  19. data/lib/dm-core/associations/one_to_many.rb +332 -0
  20. data/lib/dm-core/associations/one_to_one.rb +84 -0
  21. data/lib/dm-core/associations/relationship.rb +650 -0
  22. data/lib/dm-core/backwards.rb +11 -0
  23. data/lib/dm-core/collection.rb +1486 -0
  24. data/lib/dm-core/core_ext/kernel.rb +21 -0
  25. data/lib/dm-core/core_ext/pathname.rb +4 -0
  26. data/lib/dm-core/core_ext/symbol.rb +10 -0
  27. data/lib/dm-core/identity_map.rb +6 -0
  28. data/lib/dm-core/model/hook.rb +99 -0
  29. data/lib/dm-core/model/is.rb +30 -0
  30. data/lib/dm-core/model/property.rb +244 -0
  31. data/lib/dm-core/model/relationship.rb +366 -0
  32. data/lib/dm-core/model/scope.rb +87 -0
  33. data/lib/dm-core/model.rb +876 -0
  34. data/lib/dm-core/property/binary.rb +19 -0
  35. data/lib/dm-core/property/boolean.rb +35 -0
  36. data/lib/dm-core/property/class.rb +23 -0
  37. data/lib/dm-core/property/date.rb +45 -0
  38. data/lib/dm-core/property/date_time.rb +44 -0
  39. data/lib/dm-core/property/decimal.rb +47 -0
  40. data/lib/dm-core/property/discriminator.rb +40 -0
  41. data/lib/dm-core/property/float.rb +27 -0
  42. data/lib/dm-core/property/integer.rb +32 -0
  43. data/lib/dm-core/property/invalid_value_error.rb +17 -0
  44. data/lib/dm-core/property/lookup.rb +26 -0
  45. data/lib/dm-core/property/numeric.rb +35 -0
  46. data/lib/dm-core/property/object.rb +33 -0
  47. data/lib/dm-core/property/serial.rb +13 -0
  48. data/lib/dm-core/property/string.rb +47 -0
  49. data/lib/dm-core/property/text.rb +12 -0
  50. data/lib/dm-core/property/time.rb +46 -0
  51. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  52. data/lib/dm-core/property/typecast/time.rb +33 -0
  53. data/lib/dm-core/property.rb +856 -0
  54. data/lib/dm-core/property_set.rb +177 -0
  55. data/lib/dm-core/query/conditions/comparison.rb +886 -0
  56. data/lib/dm-core/query/conditions/operation.rb +710 -0
  57. data/lib/dm-core/query/direction.rb +33 -0
  58. data/lib/dm-core/query/operator.rb +34 -0
  59. data/lib/dm-core/query/path.rb +113 -0
  60. data/lib/dm-core/query/sort.rb +38 -0
  61. data/lib/dm-core/query.rb +1352 -0
  62. data/lib/dm-core/relationship_set.rb +69 -0
  63. data/lib/dm-core/repository.rb +226 -0
  64. data/lib/dm-core/resource/persistence_state/clean.rb +36 -0
  65. data/lib/dm-core/resource/persistence_state/deleted.rb +26 -0
  66. data/lib/dm-core/resource/persistence_state/dirty.rb +91 -0
  67. data/lib/dm-core/resource/persistence_state/immutable.rb +32 -0
  68. data/lib/dm-core/resource/persistence_state/persisted.rb +25 -0
  69. data/lib/dm-core/resource/persistence_state/transient.rb +87 -0
  70. data/lib/dm-core/resource/persistence_state.rb +70 -0
  71. data/lib/dm-core/resource.rb +1220 -0
  72. data/lib/dm-core/spec/lib/adapter_helpers.rb +63 -0
  73. data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
  74. data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
  75. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  76. data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
  77. data/lib/dm-core/spec/setup.rb +164 -0
  78. data/lib/dm-core/spec/shared/adapter_spec.rb +366 -0
  79. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  80. data/lib/dm-core/spec/shared/resource_spec.rb +1221 -0
  81. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  82. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +184 -0
  83. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  84. data/lib/dm-core/support/assertions.rb +8 -0
  85. data/lib/dm-core/support/chainable.rb +18 -0
  86. data/lib/dm-core/support/deprecate.rb +12 -0
  87. data/lib/dm-core/support/descendant_set.rb +89 -0
  88. data/lib/dm-core/support/equalizer.rb +48 -0
  89. data/lib/dm-core/support/ext/array.rb +22 -0
  90. data/lib/dm-core/support/ext/blank.rb +25 -0
  91. data/lib/dm-core/support/ext/hash.rb +67 -0
  92. data/lib/dm-core/support/ext/module.rb +47 -0
  93. data/lib/dm-core/support/ext/object.rb +57 -0
  94. data/lib/dm-core/support/ext/string.rb +24 -0
  95. data/lib/dm-core/support/ext/try_dup.rb +12 -0
  96. data/lib/dm-core/support/hook.rb +388 -0
  97. data/lib/dm-core/support/inflections.rb +60 -0
  98. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  99. data/lib/dm-core/support/inflector/methods.rb +151 -0
  100. data/lib/dm-core/support/lazy_array.rb +451 -0
  101. data/lib/dm-core/support/local_object_space.rb +13 -0
  102. data/lib/dm-core/support/logger.rb +201 -0
  103. data/lib/dm-core/support/mash.rb +176 -0
  104. data/lib/dm-core/support/naming_conventions.rb +109 -0
  105. data/lib/dm-core/support/ordered_set.rb +381 -0
  106. data/lib/dm-core/support/subject.rb +33 -0
  107. data/lib/dm-core/support/subject_set.rb +251 -0
  108. data/lib/dm-core/version.rb +3 -0
  109. data/lib/dm-core.rb +274 -0
  110. data/script/performance.rb +275 -0
  111. data/script/profile.rb +218 -0
  112. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  113. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +69 -0
  114. data/spec/public/associations/many_to_many_spec.rb +197 -0
  115. data/spec/public/associations/many_to_one_spec.rb +83 -0
  116. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  117. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  118. data/spec/public/associations/one_to_many_spec.rb +81 -0
  119. data/spec/public/associations/one_to_one_spec.rb +176 -0
  120. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  121. data/spec/public/collection_spec.rb +69 -0
  122. data/spec/public/finalize_spec.rb +77 -0
  123. data/spec/public/model/hook_spec.rb +245 -0
  124. data/spec/public/model/property_spec.rb +91 -0
  125. data/spec/public/model/relationship_spec.rb +1040 -0
  126. data/spec/public/model_spec.rb +456 -0
  127. data/spec/public/property/binary_spec.rb +43 -0
  128. data/spec/public/property/boolean_spec.rb +21 -0
  129. data/spec/public/property/class_spec.rb +27 -0
  130. data/spec/public/property/date_spec.rb +21 -0
  131. data/spec/public/property/date_time_spec.rb +21 -0
  132. data/spec/public/property/decimal_spec.rb +23 -0
  133. data/spec/public/property/discriminator_spec.rb +134 -0
  134. data/spec/public/property/float_spec.rb +22 -0
  135. data/spec/public/property/integer_spec.rb +22 -0
  136. data/spec/public/property/object_spec.rb +117 -0
  137. data/spec/public/property/serial_spec.rb +22 -0
  138. data/spec/public/property/string_spec.rb +21 -0
  139. data/spec/public/property/text_spec.rb +62 -0
  140. data/spec/public/property/time_spec.rb +21 -0
  141. data/spec/public/property_spec.rb +333 -0
  142. data/spec/public/resource/state_spec.rb +72 -0
  143. data/spec/public/resource_spec.rb +289 -0
  144. data/spec/public/sel_spec.rb +53 -0
  145. data/spec/public/setup_spec.rb +145 -0
  146. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  147. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  148. data/spec/public/shared/collection_shared_spec.rb +1637 -0
  149. data/spec/public/shared/finder_shared_spec.rb +1647 -0
  150. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  151. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
  152. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  153. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  154. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  155. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  156. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  157. data/spec/semipublic/associations_spec.rb +177 -0
  158. data/spec/semipublic/collection_spec.rb +110 -0
  159. data/spec/semipublic/model_spec.rb +96 -0
  160. data/spec/semipublic/property/binary_spec.rb +13 -0
  161. data/spec/semipublic/property/boolean_spec.rb +47 -0
  162. data/spec/semipublic/property/class_spec.rb +33 -0
  163. data/spec/semipublic/property/date_spec.rb +43 -0
  164. data/spec/semipublic/property/date_time_spec.rb +46 -0
  165. data/spec/semipublic/property/decimal_spec.rb +83 -0
  166. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  167. data/spec/semipublic/property/float_spec.rb +82 -0
  168. data/spec/semipublic/property/integer_spec.rb +82 -0
  169. data/spec/semipublic/property/lookup_spec.rb +29 -0
  170. data/spec/semipublic/property/serial_spec.rb +13 -0
  171. data/spec/semipublic/property/string_spec.rb +13 -0
  172. data/spec/semipublic/property/text_spec.rb +31 -0
  173. data/spec/semipublic/property/time_spec.rb +50 -0
  174. data/spec/semipublic/property_spec.rb +114 -0
  175. data/spec/semipublic/query/conditions/comparison_spec.rb +1502 -0
  176. data/spec/semipublic/query/conditions/operation_spec.rb +1296 -0
  177. data/spec/semipublic/query/path_spec.rb +471 -0
  178. data/spec/semipublic/query_spec.rb +3665 -0
  179. data/spec/semipublic/resource/state/clean_spec.rb +89 -0
  180. data/spec/semipublic/resource/state/deleted_spec.rb +79 -0
  181. data/spec/semipublic/resource/state/dirty_spec.rb +163 -0
  182. data/spec/semipublic/resource/state/immutable_spec.rb +107 -0
  183. data/spec/semipublic/resource/state/transient_spec.rb +163 -0
  184. data/spec/semipublic/resource/state_spec.rb +230 -0
  185. data/spec/semipublic/resource_spec.rb +23 -0
  186. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  187. data/spec/semipublic/shared/resource_shared_spec.rb +198 -0
  188. data/spec/semipublic/shared/resource_state_shared_spec.rb +91 -0
  189. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  190. data/spec/spec_helper.rb +34 -0
  191. data/spec/support/core_ext/hash.rb +10 -0
  192. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  193. data/spec/support/properties/huge_integer.rb +17 -0
  194. data/spec/unit/array_spec.rb +23 -0
  195. data/spec/unit/blank_spec.rb +73 -0
  196. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  197. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  198. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  199. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  200. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  201. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  202. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  203. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  204. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  205. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  206. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  207. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  208. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  209. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  210. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  211. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  212. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  213. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  214. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  215. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  216. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  217. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  218. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  219. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  220. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  221. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  222. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  223. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  224. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  225. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  226. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  227. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  228. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  229. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  230. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  231. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  232. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  233. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  234. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  235. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  236. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  237. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  238. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  239. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  240. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  241. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  242. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  243. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  244. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  245. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  246. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  247. data/spec/unit/hash_spec.rb +27 -0
  248. data/spec/unit/hook_spec.rb +1216 -0
  249. data/spec/unit/inflections_spec.rb +14 -0
  250. data/spec/unit/lazy_array_spec.rb +1949 -0
  251. data/spec/unit/mash_spec.rb +289 -0
  252. data/spec/unit/module_spec.rb +70 -0
  253. data/spec/unit/object_spec.rb +38 -0
  254. data/spec/unit/try_dup_spec.rb +46 -0
  255. data/tasks/ci.rake +1 -0
  256. data/tasks/spec.rake +18 -0
  257. data/tasks/yard.rake +9 -0
  258. data/tasks/yardstick.rake +19 -0
  259. metadata +323 -0
@@ -0,0 +1,197 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ shared_examples 'A Limited Many to Many Collection' do
4
+ describe '#destroy!' do
5
+ describe 'on a limited collection' do
6
+ before :all do
7
+ @other = @articles.create
8
+ @limited = @articles.all(:limit => 1)
9
+
10
+ @return = @limited.destroy!
11
+ end
12
+
13
+ it 'only removes the join resource for the destroyed resource' do
14
+ expect(@join_model.all).not_to be_empty
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ # run the specs once with a loaded association and once not
21
+ [ false, true ].each do |loaded|
22
+ describe 'Many to Many Associations with :through => Resource' do
23
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
24
+
25
+ self.loaded = loaded
26
+
27
+ # define the model prior to supported_by
28
+ before :all do
29
+ module ::Blog
30
+ class Author
31
+ include DataMapper::Resource
32
+
33
+ property :id, Serial
34
+ property :name, String
35
+
36
+ has n, :articles, :through => Resource
37
+ end
38
+
39
+ class Article
40
+ include DataMapper::Resource
41
+
42
+ property :id, Serial
43
+ property :title, String, :required => true
44
+ property :content, Text
45
+ property :subtitle, String
46
+ property :attachment, Object
47
+
48
+ has n, :authors, :through => Resource
49
+ belongs_to :original, self, :required => false
50
+ has n, :revisions, self, :child_key => [ :original_id ]
51
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
52
+ has n, :publications, :through => Resource
53
+ end
54
+
55
+ class Publication
56
+ include DataMapper::Resource
57
+
58
+ property :id, Serial
59
+ property :name, String
60
+
61
+ has n, :articles, :through => Resource
62
+ end
63
+ end
64
+
65
+ @author_model = Blog::Author
66
+ @article_model = Blog::Article
67
+ @publication_model = Blog::Publication
68
+
69
+ # initialize the join model
70
+ DataMapper.finalize
71
+
72
+ @join_model = Blog::ArticleAuthor
73
+ end
74
+
75
+ supported_by :all do
76
+ before :all do
77
+ @author = @author_model.create(:name => 'Dan Kubb')
78
+
79
+ @original = @author.articles.create(:title => 'Original Article')
80
+ @article = @author.articles.create(:title => 'Sample Article', :content => 'Sample', :original => @original)
81
+ @other = @author.articles.create(:title => 'Other Article', :content => 'Other')
82
+
83
+ # load the targets without references to a single source
84
+ load_collection = lambda do |query|
85
+ @author_model.get!(*@author.key).articles(query)
86
+ end
87
+
88
+ @articles = load_collection.call(:title => 'Sample Article')
89
+ @other_articles = load_collection.call(:title => 'Other Article')
90
+
91
+ @articles.entries if loaded
92
+ end
93
+
94
+ it_behaves_like 'A public Collection'
95
+ it_behaves_like 'A public Association Collection'
96
+ it_behaves_like 'A Collection supporting Strategic Eager Loading' unless loaded
97
+ it_behaves_like 'Finder Interface'
98
+ it_behaves_like 'Collection Finder Interface'
99
+ it_behaves_like 'A Limited Many to Many Collection'
100
+ end
101
+ end
102
+
103
+ describe 'Many to Many Associations :through => one_to_many' do
104
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
105
+
106
+ self.loaded = loaded
107
+
108
+ # define the model prior to supported_by
109
+ before :all do
110
+ module ::Blog
111
+ class Author
112
+ include DataMapper::Resource
113
+
114
+ property :id, Serial
115
+ property :name, String
116
+
117
+ has n, :sites
118
+ has n, :articles, :through => :sites
119
+ end
120
+
121
+ class Site
122
+ include DataMapper::Resource
123
+
124
+ property :name, String, :key => true, :default => 'default'
125
+
126
+ belongs_to :author
127
+ has n, :articles
128
+ end
129
+
130
+ class Article
131
+ include DataMapper::Resource
132
+
133
+ property :id, Serial
134
+ property :title, String, :required => true
135
+ property :content, Text
136
+ property :subtitle, String
137
+ property :attachment, Object
138
+
139
+ property :site_name, String, :default => 'default'
140
+
141
+ belongs_to :site
142
+ has n, :authors, :through => :site
143
+ belongs_to :original, self, :required => false
144
+ has n, :revisions, self, :child_key => [ :original_id ]
145
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
146
+ has n, :publications, :through => Resource
147
+ end
148
+
149
+ class Publication
150
+ include DataMapper::Resource
151
+
152
+ property :id, Serial
153
+ property :name, String
154
+
155
+ has n, :articles, :through => Resource
156
+ end
157
+ end
158
+
159
+ @author_model = Blog::Author
160
+ @article_model = Blog::Article
161
+ @publication_model = Blog::Publication
162
+
163
+ @join_model = Blog::Site
164
+ end
165
+
166
+ supported_by :all do
167
+ before :all do
168
+ @author = @author_model.create(:name => 'Dan Kubb')
169
+
170
+ @original_site = @author.sites.create(:name => 'original')
171
+ @article_site = @author.sites.create(:name => 'article')
172
+ @other_site = @author.sites.create(:name => 'other')
173
+
174
+ @original = @original_site.articles.create(:title => 'Original Article')
175
+ @article = @article_site.articles.create(:title => 'Sample Article', :content => 'Sample', :original => @original)
176
+ @other = @other_site.articles.create(:title => 'Other Article', :content => 'Other')
177
+
178
+ # load the targets without references to a single source
179
+ load_collection = lambda do |query|
180
+ @author_model.get!(*@author.key).articles(query)
181
+ end
182
+
183
+ @articles = load_collection.call(:title => 'Sample Article')
184
+ @other_articles = load_collection.call(:title => 'Other Article')
185
+
186
+ @articles.entries if loaded
187
+ end
188
+
189
+ it_behaves_like 'A public Collection'
190
+ it_behaves_like 'A public Association Collection'
191
+ it_behaves_like 'A Collection supporting Strategic Eager Loading' unless loaded
192
+ it_behaves_like 'Finder Interface'
193
+ it_behaves_like 'Collection Finder Interface'
194
+ it_behaves_like 'A Limited Many to Many Collection'
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,83 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'Many to One Associations' do
4
+ before :all do
5
+ module ::Blog
6
+ class User
7
+ include DataMapper::Resource
8
+
9
+ property :name, String, :key => true
10
+ property :age, Integer
11
+ property :summary, Text
12
+ property :description, Text
13
+ property :admin, Boolean, :accessor => :private
14
+
15
+ belongs_to :parent, self, :required => false
16
+ has n, :children, self, :inverse => :parent
17
+
18
+ belongs_to :referrer, self, :required => false
19
+ has n, :comments
20
+
21
+ # FIXME: figure out a different approach than stubbing things out
22
+ def comment=(*)
23
+ # do nothing with comment
24
+ end
25
+ end
26
+
27
+ class Author < User; end
28
+
29
+ class Comment
30
+ include DataMapper::Resource
31
+
32
+ property :id, Serial
33
+ property :body, Text
34
+
35
+ belongs_to :user
36
+ end
37
+
38
+ class Article
39
+ include DataMapper::Resource
40
+
41
+ property :id, Serial
42
+ property :body, Text
43
+
44
+ has n, :paragraphs
45
+ end
46
+
47
+ class Paragraph
48
+ include DataMapper::Resource
49
+
50
+ property :id, Serial
51
+ property :text, String
52
+
53
+ belongs_to :article
54
+ end
55
+ end
56
+
57
+ class ::Default
58
+ include DataMapper::Resource
59
+
60
+ property :name, String, :key => true, :default => 'a default value'
61
+ end
62
+ DataMapper.finalize
63
+
64
+ @user_model = Blog::User
65
+ @author_model = Blog::Author
66
+ @comment_model = Blog::Comment
67
+ @article_model = Blog::Article
68
+ @paragraph_model = Blog::Paragraph
69
+ end
70
+
71
+ supported_by :all do
72
+ before :all do
73
+ user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test')
74
+ comment = @comment_model.create(:body => 'Cool spec', :user => user)
75
+
76
+ @comment = @comment_model.get!(*comment.key)
77
+ @user = @comment.user
78
+ end
79
+
80
+ it_behaves_like 'A public Resource'
81
+ it_behaves_like 'A Resource supporting Strategic Eager Loading'
82
+ end
83
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ # TODO: combine this into many_to_one_spec.rb
4
+
5
+ describe 'Many to One Associations when foreign key is part of a composite key, with an integer and a boolean making up the composite key' do
6
+ before :all do
7
+ class ::ManyModel
8
+ include DataMapper::Resource
9
+
10
+ property :integer_key, Integer, :key => true
11
+ property :boolean_key, Boolean, :key => true
12
+
13
+ belongs_to :one_model, :child_key => [ :integer_key ]
14
+ end
15
+
16
+ class ::OneModel
17
+ include DataMapper::Resource
18
+
19
+ property :integer_key, Integer, :key => true
20
+
21
+ has n, :many_models, :child_key => [ :integer_key ]
22
+ end
23
+ DataMapper.finalize
24
+ end
25
+
26
+ supported_by :all do
27
+ before :all do
28
+ @one = OneModel.create(:integer_key => 1)
29
+ @many = ManyModel.create(:integer_key => 1, :boolean_key => false)
30
+ end
31
+
32
+ it 'is able to access parent' do
33
+ expect(@many.one_model).to eq @one
34
+ end
35
+
36
+ it 'is able to access the child' do
37
+ expect(@one.many_models).to eq [@many]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ # TODO: combine this into many_to_one_spec.rb
4
+
5
+ describe 'Many to One Associations when foreign key is a property subclass' do
6
+ before :all do
7
+ class ::CustomPK < DataMapper::Property::String
8
+ key true
9
+ end
10
+
11
+ class ::Animal
12
+ include DataMapper::Resource
13
+
14
+ property :id, Serial
15
+ property :name, String
16
+
17
+ belongs_to :zoo
18
+ end
19
+
20
+ class ::Zoo
21
+ include DataMapper::Resource
22
+
23
+ property :id, ::CustomPK
24
+
25
+ has n, :animals
26
+ end
27
+
28
+ DataMapper.finalize
29
+ end
30
+
31
+ supported_by :all do
32
+ before :all do
33
+ @zoo = Zoo.create(:id => 'foo')
34
+ @animal = @zoo.animals.create(:name => 'marty')
35
+ end
36
+
37
+ it 'has FK of the same property type as zoo PK' do
38
+ expect(Animal.properties[:zoo_id].class).to be(Zoo.properties[:id].class)
39
+ end
40
+
41
+ it 'is able to access parent' do
42
+ expect(@animal.zoo).to eq @zoo
43
+ end
44
+
45
+ it 'is able to access the children' do
46
+ expect(@zoo.animals).to eq [@animal]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,81 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ # run the specs once with a loaded association and once not
4
+ [ false, true ].each do |loaded|
5
+ describe 'One to Many Associations' do
6
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
7
+
8
+ self.loaded = loaded
9
+
10
+ # define the model prior to supported_by
11
+ before :all do
12
+ module ::Blog
13
+ class Author
14
+ include DataMapper::Resource
15
+
16
+ property :id, Serial
17
+ property :name, String
18
+
19
+ has n, :articles
20
+ end
21
+
22
+ class Article
23
+ include DataMapper::Resource
24
+
25
+ property :id, Serial
26
+ property :title, String, :required => true
27
+ property :content, Text
28
+ property :subtitle, String
29
+ property :attachment, Object
30
+
31
+ belongs_to :author, :required => false
32
+ belongs_to :original, self, :required => false
33
+ has n, :revisions, self, :child_key => [ :original_id ]
34
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
35
+ has n, :publications, :through => Resource
36
+ end
37
+
38
+ class Publication
39
+ include DataMapper::Resource
40
+
41
+ property :id, Serial
42
+ property :name, String
43
+
44
+ has n, :articles, :through => Resource
45
+ end
46
+ end
47
+
48
+ DataMapper.finalize
49
+
50
+ @author_model = Blog::Author
51
+ @article_model = Blog::Article
52
+ @publication_model = Blog::Publication
53
+ end
54
+
55
+ supported_by :all do
56
+ before :all do
57
+ @author = @author_model.create(:name => 'Dan Kubb')
58
+
59
+ @original = @author.articles.create(:title => 'Original Article')
60
+ @article = @author.articles.create(:title => 'Sample Article', :content => 'Sample', :original => @original)
61
+ @other = @author.articles.create(:title => 'Other Article', :content => 'Other')
62
+
63
+ # load the targets without references to a single source
64
+ load_collection = lambda do |query|
65
+ @author_model.get!(*@author.key).articles(query)
66
+ end
67
+
68
+ @articles = load_collection.call(:title => 'Sample Article')
69
+ @other_articles = load_collection.call(:title => 'Other Article')
70
+
71
+ @articles.entries if loaded
72
+ end
73
+
74
+ it_behaves_like 'A public Collection'
75
+ it_behaves_like 'A public Association Collection'
76
+ it_behaves_like 'A Collection supporting Strategic Eager Loading'
77
+ it_behaves_like 'Finder Interface'
78
+ it_behaves_like 'Collection Finder Interface'
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,176 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe 'One to One Associations' do
4
+ before :all do
5
+ module ::Blog
6
+ class User
7
+ include DataMapper::Resource
8
+
9
+ property :name, String, :key => true
10
+ property :age, Integer
11
+ property :summary, Text
12
+ property :description, Text
13
+ property :admin, Boolean, :accessor => :private
14
+
15
+ belongs_to :parent, self, :required => false
16
+ has n, :children, self, :inverse => :parent
17
+
18
+ belongs_to :referrer, self, :required => false
19
+ belongs_to :comment
20
+
21
+ # TODO: remove this after Relationship#inverse can dynamically
22
+ # create an inverse relationship when no perfect match can be found
23
+ has n, :referree, self, :child_key => [ :referrer_name ]
24
+ end
25
+
26
+ class Author < User; end
27
+
28
+ class Comment
29
+ include DataMapper::Resource
30
+
31
+ property :id, Serial
32
+ property :body, Text
33
+
34
+ has 1, :user
35
+ end
36
+
37
+ class Article
38
+ include DataMapper::Resource
39
+
40
+ property :id, Serial
41
+ property :body, Text
42
+
43
+ has 1, :paragraph
44
+ end
45
+
46
+ class Paragraph
47
+ include DataMapper::Resource
48
+
49
+ property :id, Serial
50
+ property :text, String
51
+
52
+ belongs_to :article
53
+ end
54
+ end
55
+
56
+ class ::Default
57
+ include DataMapper::Resource
58
+
59
+ property :name, String, :key => true, :default => 'a default value'
60
+ end
61
+ DataMapper.finalize
62
+
63
+ @user_model = Blog::User
64
+ @author_model = Blog::Author
65
+ @comment_model = Blog::Comment
66
+ @article_model = Blog::Article
67
+ @paragraph_model = Blog::Paragraph
68
+ end
69
+
70
+ supported_by :all do
71
+ before :all do
72
+ comment = @comment_model.create(:body => 'Cool spec')
73
+ user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test', :comment => comment)
74
+
75
+ @comment = @comment_model.get!(*comment.key)
76
+ @user = @comment.user
77
+ end
78
+
79
+ it_behaves_like 'A public Resource'
80
+ it_behaves_like 'A Resource supporting Strategic Eager Loading'
81
+ end
82
+ end
83
+
84
+ describe 'One to One Through Associations' do
85
+ before :all do
86
+ module ::Blog
87
+ class Referral
88
+ include DataMapper::Resource
89
+
90
+ property :referrer_name, String, :key => true
91
+ property :referree_name, String, :key => true
92
+
93
+ belongs_to :referrer, 'User', :child_key => [ :referrer_name ]
94
+ belongs_to :referree, 'User', :child_key => [ :referree_name ]
95
+ end
96
+
97
+ class User
98
+ include DataMapper::Resource
99
+
100
+ property :name, String, :key => true
101
+ property :age, Integer
102
+ property :summary, Text
103
+ property :description, Text
104
+ property :admin, Boolean, :accessor => :private
105
+
106
+ belongs_to :parent, self, :required => false
107
+ has n, :children, self, :inverse => :parent
108
+
109
+ has 1, :referral_from, Referral, :child_key => [ :referree_name ]
110
+ has 1, :referral_to, Referral, :child_key => [ :referrer_name ]
111
+
112
+ has 1, :referrer, self, :through => :referral_from
113
+ has 1, :referree, self, :through => :referral_to
114
+ has 1, :comment, :through => Resource
115
+ end
116
+
117
+ class Author < User; end
118
+
119
+ class Comment
120
+ include DataMapper::Resource
121
+
122
+ property :id, Serial
123
+ property :body, Text
124
+
125
+ has 1, :user, :through => Resource
126
+ end
127
+
128
+ class Article
129
+ include DataMapper::Resource
130
+
131
+ property :id, Serial
132
+ property :body, Text
133
+
134
+ has 1, :paragraph, :through => Resource
135
+ end
136
+
137
+ class Paragraph
138
+ include DataMapper::Resource
139
+
140
+ property :id, Serial
141
+ property :text, String
142
+
143
+ has 1, :article, :through => Resource
144
+ end
145
+ end
146
+
147
+ class ::Default
148
+ include DataMapper::Resource
149
+
150
+ property :name, String, :key => true, :default => 'a default value'
151
+ end
152
+ DataMapper.finalize
153
+
154
+ @referral_model = Blog::Referral
155
+ @user_model = Blog::User
156
+ @author_model = Blog::Author
157
+ @comment_model = Blog::Comment
158
+ @article_model = Blog::Article
159
+ @paragraph_model = Blog::Paragraph
160
+ end
161
+
162
+ supported_by :all do
163
+ before :all do
164
+ comment = @comment_model.create(:body => 'Cool spec')
165
+ user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test', :comment => comment)
166
+
167
+ @comment = @comment_model.get!(*comment.key)
168
+ @user = @comment.user
169
+ end
170
+
171
+ it_behaves_like 'A public Resource'
172
+
173
+ # TODO: make this pass
174
+ # it_behaves_like 'A Resource supporting Strategic Eager Loading'
175
+ end
176
+ end
@@ -0,0 +1,46 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ # TODO: combine this into one_to_one_spec.rb
4
+
5
+ describe 'One to One Associations when foreign key is part of a composite key and contains a boolean, with an integer and a boolean making up the composite key' do
6
+ before :all do
7
+ class ::ParentModel
8
+ include DataMapper::Resource
9
+
10
+ property :integer_key, Integer, :key => true
11
+ property :boolean_key, Boolean, :key => true
12
+
13
+ has 1, :child_model, :child_key => [ :integer_key, :boolean_key ]
14
+ end
15
+
16
+ class ::ChildModel
17
+ include DataMapper::Resource
18
+
19
+ property :integer_key, Integer, :key => true
20
+ property :other_integer_key, Integer, :key => true
21
+ property :boolean_key, Boolean, :key => true
22
+
23
+ belongs_to :parent_model, :child_key => [ :integer_key, :boolean_key ]
24
+ end
25
+ DataMapper.finalize
26
+ end
27
+
28
+ supported_by :all do
29
+ before :all do
30
+ @parent = ParentModel.create(:integer_key => 1, :boolean_key => false)
31
+ @child = ChildModel.create(:integer_key => 1, :other_integer_key => 1, :boolean_key => false)
32
+ end
33
+
34
+ it 'is able to access the child' do
35
+ expect(@parent.child_model).to eq @child
36
+ end
37
+
38
+ it 'is able to access the parent' do
39
+ expect(@child.parent_model).to eq @parent
40
+ end
41
+
42
+ it 'is able to access the parent_key' do
43
+ expect(@child.parent_model.key).not_to be_nil
44
+ end
45
+ end
46
+ end