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,456 @@
1
+ require_relative '../spec_helper'
2
+
3
+ # TODO: move these specs into shared specs for #copy
4
+ describe DataMapper::Model do
5
+ before :all do
6
+ module ::Blog
7
+ class Article
8
+ include DataMapper::Resource
9
+
10
+ property :id, Serial
11
+ property :title, String, :required => true
12
+ property :content, Text, :writer => :private, :default => lambda { |resource, property| resource.title }
13
+ property :subtitle, String
14
+ property :author, String, :required => true
15
+
16
+ belongs_to :original, self, :required => false
17
+ has n, :revisions, self, :child_key => [ :original_id ]
18
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
19
+ end
20
+ end
21
+ DataMapper.finalize
22
+
23
+ @article_model = Blog::Article
24
+ end
25
+
26
+ supported_by :all do
27
+ before :all do
28
+ @author = 'Dan Kubb'
29
+
30
+ @original = @article_model.create(:title => 'Original Article', :author => @author)
31
+ @article = @article_model.create(:title => 'Sample Article', :original => @original, :author => @author)
32
+ @other = @article_model.create(:title => 'Other Article', :author => @author)
33
+ end
34
+
35
+ it { expect(@article_model).to respond_to(:copy) }
36
+
37
+ describe '#copy' do
38
+ with_alternate_adapter do
39
+ before :all do
40
+ if @article_model.respond_to?(:auto_migrate!)
41
+ # force the article model to be available in the alternate repository
42
+ @article_model.auto_migrate!(@adapter.name)
43
+ end
44
+ end
45
+
46
+ describe 'between identical models' do
47
+ before :all do
48
+ @return = @resources = @article_model.copy(@repository.name, @adapter.name)
49
+ end
50
+
51
+ it 'returns a Collection' do
52
+ expect(@return).to be_a_kind_of(DataMapper::Collection)
53
+ end
54
+
55
+ it 'returns Resources' do
56
+ @return.each { |resource| expect(resource).to be_a_kind_of(DataMapper::Resource) }
57
+ end
58
+
59
+ it 'has each Resource set to the expected Repository' do
60
+ @resources.each { |resource| expect(resource.repository.name).to eq @adapter.name }
61
+ end
62
+
63
+ it 'creates the Resources in the expected Repository' do
64
+ expect(@article_model.all(repository: DataMapper.repository(@adapter.name))).to eq @resources
65
+ end
66
+ end
67
+
68
+ describe 'between different models' do
69
+ before :all do
70
+ @other.destroy
71
+ @article.destroy
72
+ @original.destroy
73
+
74
+ # make sure the default repository is empty
75
+ expect(@article_model.all(repository: @repository)).to be_empty
76
+
77
+ # add an extra property to the alternate model
78
+ DataMapper.repository(@adapter.name) do
79
+ @article_model.property :status, String, :default => 'new'
80
+ end
81
+
82
+ if @article_model.respond_to?(:auto_migrate!)
83
+ @article_model.auto_migrate!(@adapter.name)
84
+ end
85
+
86
+ # add new resources to the alternate repository
87
+ DataMapper.repository(@adapter.name) do
88
+ # use an id value that is unique
89
+ @heff1 = @article_model.create(:id => 99, :title => 'Alternate Repository', :author => @author)
90
+ end
91
+
92
+ # copy from the alternate to the default repository
93
+ @return = @resources = @article_model.copy(@adapter.name, :default)
94
+ end
95
+
96
+ it 'returns a Collection' do
97
+ expect(@return).to be_a_kind_of(DataMapper::Collection)
98
+ end
99
+
100
+ it 'returns Resources' do
101
+ @return.each { |resource| expect(resource).to be_a_kind_of(DataMapper::Resource) }
102
+ end
103
+
104
+ it 'has each Resource set to the expected Repository' do
105
+ @resources.each { |resource| expect(resource.repository.name).to eq :default }
106
+ end
107
+
108
+ it 'returns the expected resources' do
109
+ # match on id because resources from different repositories are different
110
+ expect(@resources.map { |resource| resource.id }).to eq [@heff1.id]
111
+ end
112
+
113
+ it 'adds the resources to the alternate repository' do
114
+ expect(@article.model.get!(*@heff1.key)).not_to be_nil
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ describe DataMapper::Model do
123
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
124
+
125
+ self.loaded = false
126
+
127
+ before :all do
128
+ module ::Blog
129
+ class Article
130
+ include DataMapper::Resource
131
+
132
+ property :id, Serial
133
+ property :title, String, :required => true, :default => 'Default Title'
134
+ property :content, Text
135
+ property :subtitle, String
136
+
137
+ belongs_to :original, self, :required => false
138
+ has n, :revisions, self, :child_key => [ :original_id ]
139
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
140
+ has n, :publications, :through => Resource
141
+ end
142
+
143
+ class Publication
144
+ include DataMapper::Resource
145
+
146
+ property :id, Serial
147
+ property :name, String
148
+
149
+ has n, :articles, :through => Resource
150
+ end
151
+ end
152
+ DataMapper.finalize
153
+
154
+ @article_model = Blog::Article
155
+ @publication_model = Blog::Publication
156
+ end
157
+
158
+ supported_by :all do
159
+ # model cannot be a kicker
160
+ def should_not_be_a_kicker; end
161
+
162
+ def model?; true end
163
+
164
+ before :all do
165
+ @articles = @article_model
166
+
167
+ @original = @articles.create(:title => 'Original Article')
168
+ @article = @articles.create(:title => 'Sample Article', :content => 'Sample', :original => @original)
169
+ @other = @articles.create(:title => 'Other Article', :content => 'Other')
170
+ end
171
+
172
+ describe '#new' do
173
+ subject { model.new(*args) }
174
+
175
+ let(:model) { @article_model }
176
+
177
+ context 'with no arguments' do
178
+ let(:args) { [] }
179
+
180
+ it { is_expected.to be_instance_of(model) }
181
+
182
+ its(:attributes) { is_expected.to eq({title: 'Default Title'}) }
183
+ end
184
+
185
+ context 'with an empty Hash' do
186
+ let(:args) { [ {} ] }
187
+
188
+ it { is_expected.to be_instance_of(model) }
189
+ its(:attributes) { is_expected.to eq({title: 'Default Title'}) }
190
+ end
191
+
192
+ context 'with a non-empty Hash' do
193
+ let(:attributes) { { :title => 'A Title' } }
194
+ let(:args) { [ attributes ] }
195
+
196
+ it { is_expected.to be_instance_of(model) }
197
+
198
+ its(:attributes) { is_expected.to eq attributes }
199
+ end
200
+
201
+ context 'with nil' do
202
+ let(:args) { [nil] }
203
+
204
+ it { is_expected.to be_instance_of(model) }
205
+ its(:attributes) { is_expected.to eq({title: 'Default Title'}) }
206
+ end
207
+ end
208
+
209
+ [ :create, :create! ].each do |method|
210
+ describe "##{method}" do
211
+ subject { model.send(method, *args) }
212
+
213
+ let(:model) { @article_model }
214
+
215
+ context 'with no arguments' do
216
+ let(:args) { [] }
217
+
218
+ it { is_expected.to be_instance_of(model) }
219
+
220
+ it { is_expected.to be_saved }
221
+ end
222
+
223
+ context 'with an empty Hash' do
224
+ let(:args) { [ {} ] }
225
+
226
+
227
+ it { is_expected.to be_instance_of(model) }
228
+ it { is_expected.to be_saved }
229
+ end
230
+
231
+ context 'with a non-empty Hash' do
232
+ let(:attributes) { { :title => 'A Title' } }
233
+ let(:args) { [ attributes ] }
234
+
235
+ it { is_expected.to be_instance_of(model) }
236
+ it { is_expected.to be_saved }
237
+ its(:title) { is_expected.to eq attributes[:title] }
238
+ end
239
+
240
+ context 'with nil' do
241
+ let(:args) { [ nil ] }
242
+
243
+
244
+ it { is_expected.to be_instance_of(model) }
245
+ it { is_expected.to be_saved }
246
+ end
247
+ end
248
+ end
249
+
250
+ [ :destroy, :destroy! ].each do |method|
251
+ describe "##{method}" do
252
+ subject { model.send(method) }
253
+
254
+ let(:model) { @article_model }
255
+
256
+ it 'removes all resources' do
257
+ expect(method(:subject)).to change { model.any? }.from(true).to(false)
258
+ end
259
+ end
260
+ end
261
+
262
+ [ :update, :update! ].each do |method|
263
+ describe "##{method}" do
264
+ subject { model.send(method, *args) }
265
+
266
+ let(:model) { @article_model }
267
+
268
+ context 'with attributes' do
269
+ let(:attributes) { { :title => 'Updated Title' } }
270
+ let(:args) { [ attributes ] }
271
+
272
+ it { is_expected.to be(true) }
273
+
274
+ it 'persists the changes' do
275
+ subject
276
+ expect(model.all(fields: [:title]).map { |resource| resource.title }.uniq).to eq [attributes[:title]]
277
+ end
278
+ end
279
+
280
+ context 'with attributes where one is a parent association' do
281
+ let(:attributes) { { :original => @other } }
282
+ let(:args) { [ attributes ] }
283
+
284
+ it { is_expected.to be(true) }
285
+
286
+ it 'persists the changes' do
287
+ subject
288
+ expect(model.all(fields: [:original_id]).map { |resource| resource.original }.uniq).to eq [attributes[:original]]
289
+ end
290
+ end
291
+
292
+ context 'with attributes where a required property is nil' do
293
+ let(:attributes) { { :title => nil } }
294
+ let(:args) { [ attributes ] }
295
+
296
+ it 'raises InvalidValueError' do
297
+ expect { subject }.to(raise_error(DataMapper::Property::InvalidValueError) do |error|
298
+ expect(error.property).to eq model.title
299
+ end)
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ it_behaves_like 'Finder Interface'
306
+
307
+ it 'DataMapper::Model responds to raise_on_save_failure' do
308
+ expect(DataMapper::Model).to respond_to(:raise_on_save_failure)
309
+ end
310
+
311
+ describe '.raise_on_save_failure' do
312
+ subject { DataMapper::Model.raise_on_save_failure }
313
+
314
+ it { is_expected.to be(false) }
315
+ end
316
+
317
+ it 'DataMapper::Model responds to raise_on_save_failure=' do
318
+ expect(DataMapper::Model).to respond_to(:raise_on_save_failure=)
319
+ end
320
+
321
+ describe '.raise_on_save_failure=' do
322
+ after do
323
+ # reset to the default value
324
+ reset_raise_on_save_failure(DataMapper::Model)
325
+ end
326
+
327
+ subject { DataMapper::Model.raise_on_save_failure = @value }
328
+
329
+ describe 'with a true value' do
330
+ before do
331
+ @value = true
332
+ end
333
+
334
+ it { is_expected.to be(true) }
335
+
336
+ it 'sets raise_on_save_failure' do
337
+ expect(method(:subject)).to change {
338
+ DataMapper::Model.raise_on_save_failure
339
+ }.from(false).to(true)
340
+ end
341
+ end
342
+
343
+ describe 'with a false value' do
344
+ before do
345
+ @value = false
346
+ end
347
+
348
+ it { is_expected.to be(false) }
349
+
350
+ it 'sets raise_on_save_failure' do
351
+ expect(method(:subject)).not_to change {
352
+ DataMapper::Model.raise_on_save_failure
353
+ }
354
+ end
355
+ end
356
+ end
357
+
358
+ it 'A model responds to raise_on_save_failure' do
359
+ expect(@article_model).to respond_to(:raise_on_save_failure)
360
+ end
361
+
362
+ describe '#raise_on_save_failure' do
363
+ after do
364
+ # reset to the default value
365
+ reset_raise_on_save_failure(DataMapper::Model)
366
+ reset_raise_on_save_failure(@article_model)
367
+ end
368
+
369
+ subject { @article_model.raise_on_save_failure }
370
+
371
+ describe 'when DataMapper::Model.raise_on_save_failure has not been set' do
372
+ it { is_expected.to be(false) }
373
+ end
374
+
375
+ describe 'when DataMapper::Model.raise_on_save_failure has been set to true' do
376
+ before do
377
+ DataMapper::Model.raise_on_save_failure = true
378
+ end
379
+
380
+ it { is_expected.to be(true) }
381
+ end
382
+
383
+ describe 'when model.raise_on_save_failure has been set to true' do
384
+ before do
385
+ @article_model.raise_on_save_failure = true
386
+ end
387
+
388
+ it { is_expected.to be(true) }
389
+ end
390
+ end
391
+
392
+ it 'A model responds to raise_on_save_failure=' do
393
+ expect(@article_model).to respond_to(:raise_on_save_failure=)
394
+ end
395
+
396
+ describe '#raise_on_save_failure=' do
397
+ after do
398
+ # reset to the default value
399
+ reset_raise_on_save_failure(@article_model)
400
+ end
401
+
402
+ subject { @article_model.raise_on_save_failure = @value }
403
+
404
+ describe 'with a true value' do
405
+ before do
406
+ @value = true
407
+ end
408
+
409
+ it { is_expected.to be(true) }
410
+
411
+ it 'sets raise_on_save_failure' do
412
+ expect(method(:subject)).to change {
413
+ @article_model.raise_on_save_failure
414
+ }.from(false).to(true)
415
+ end
416
+ end
417
+
418
+ describe 'with a false value' do
419
+ before do
420
+ @value = false
421
+ end
422
+
423
+ it { is_expected.to be(false) }
424
+
425
+ it 'sets raise_on_save_failure' do
426
+ expect(method(:subject)).not_to change {
427
+ @article_model.raise_on_save_failure
428
+ }
429
+ end
430
+ end
431
+ end
432
+
433
+ it 'A model responds to allowed_writer_methods' do
434
+ expect(@article_model).to respond_to(:allowed_writer_methods)
435
+ end
436
+
437
+ describe '#allowed_writer_methods' do
438
+ subject { @article_model.allowed_writer_methods }
439
+
440
+ let(:expected_writer_methods) do
441
+ %w[ original= revisions= previous= publications= article_publications=
442
+ id= title= content= subtitle= original_id= persisted_state= ].to_set
443
+ end
444
+
445
+ it { is_expected.to be_kind_of(Set) }
446
+ it { is_expected.to be_all { |method| method.is_a?(String) } }
447
+ it { is_expected.to be_frozen }
448
+
449
+ it 'is idempotent' do
450
+ is_expected.to equal(instance_eval(&self.class.subject))
451
+ end
452
+
453
+ it { is_expected.to eql(expected_writer_methods) }
454
+ end
455
+ end
456
+ end
@@ -0,0 +1,43 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe DataMapper::Property::Binary do
4
+ before :all do
5
+ @name = :title
6
+ @type = described_class
7
+ @load_as = String
8
+ @value = 'value'
9
+ @other_value = 'return value'
10
+ @invalid_value = 1
11
+ end
12
+
13
+ it_behaves_like 'A public Property'
14
+
15
+ describe '.options' do
16
+ subject { described_class.options }
17
+
18
+ it { is_expected.to eql(load_as: @load_as, dump_as: @load_as, length: 50) }
19
+ end
20
+
21
+ if RUBY_VERSION >= "1.9"
22
+ describe 'encoding' do
23
+ let(:model) do
24
+ Class.new do
25
+ include ::DataMapper::Resource
26
+ property :bin_data, ::DataMapper::Property::Binary
27
+ end
28
+ end
29
+
30
+ it 'always dumps with BINARY' do
31
+ expect(model.bin_data.dump('foo'.freeze).encoding.names).to include('BINARY')
32
+ end
33
+
34
+ it 'always loads with BINARY' do
35
+ expect(model.bin_data.load('foo'.freeze).encoding.names).to include('BINARY')
36
+ end
37
+
38
+ it 'has valid options' do
39
+ expect(model.bin_data.options).to eql(load_as: @load_as, dump_as: @load_as, length: 50)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe DataMapper::Property::Boolean do
4
+ before :all do
5
+ @name = :active
6
+ @type = described_class
7
+ @load_as = TrueClass
8
+ @value = true
9
+ @other_value = false
10
+ @invalid_value = 1
11
+ end
12
+
13
+ it_behaves_like 'A public Property'
14
+
15
+ describe '.options' do
16
+ subject { described_class.options }
17
+
18
+ it { is_expected.to be_kind_of(Hash) }
19
+ it { is_expected.to eql(load_as: @load_as, dump_as: @load_as) }
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe DataMapper::Property::Class do
4
+ before :all do
5
+ Object.send(:remove_const, :Foo) if defined?(Foo)
6
+ Object.send(:remove_const, :Bar) if defined?(Bar)
7
+
8
+ class ::Foo; end
9
+ class ::Bar; end
10
+
11
+ @name = :type
12
+ @type = described_class
13
+ @load_as = Class
14
+ @value = Foo
15
+ @other_value = Bar
16
+ @invalid_value = 1
17
+ end
18
+
19
+ it_behaves_like 'A public Property'
20
+
21
+ describe '.options' do
22
+ subject { described_class.options }
23
+
24
+ it { is_expected.to be_kind_of(Hash) }
25
+ it { is_expected.to eql(load_as: @load_as, dump_as: @load_as) }
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe DataMapper::Property::Date do
4
+ before :all do
5
+ @name = :created_on
6
+ @type = described_class
7
+ @load_as = Date
8
+ @value = Date.today
9
+ @other_value = Date.today + 1
10
+ @invalid_value = 1
11
+ end
12
+
13
+ it_behaves_like 'A public Property'
14
+
15
+ describe '.options' do
16
+ subject { described_class.options }
17
+
18
+ it { is_expected.to be_kind_of(Hash) }
19
+ it { is_expected.to eql(load_as: @load_as, dump_as: @load_as) }
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe DataMapper::Property::DateTime do
4
+ before :all do
5
+ @name = :created_at
6
+ @type = described_class
7
+ @load_as = DateTime
8
+ @value = DateTime.now
9
+ @other_value = DateTime.now + 15
10
+ @invalid_value = 1
11
+ end
12
+
13
+ it_behaves_like 'A public Property'
14
+
15
+ describe '.options' do
16
+ subject { described_class.options }
17
+
18
+ it { is_expected.to be_kind_of(Hash) }
19
+ it { is_expected.to eql(load_as: @load_as, dump_as: @load_as) }
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe DataMapper::Property::Decimal do
4
+ before :all do
5
+ @name = :rate
6
+ @type = described_class
7
+ @options = { :precision => 5, :scale => 2 }
8
+ @load_as = BigDecimal
9
+ @dump_as = String
10
+ @value = BigDecimal('1.0')
11
+ @other_value = BigDecimal('2.0')
12
+ @invalid_value = true
13
+ end
14
+
15
+ it_behaves_like 'A public Property'
16
+
17
+ describe '.options' do
18
+ subject { described_class.options }
19
+
20
+ it { is_expected.to be_kind_of(Hash) }
21
+ it { is_expected.to eql(load_as: @load_as, dump_as: @load_as, precision: 10, scale: 0) }
22
+ end
23
+ end