ardm-core 1.2.1

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 +35 -0
  5. data/.travis.yml +23 -0
  6. data/.yardopts +1 -0
  7. data/Gemfile +63 -0
  8. data/LICENSE +20 -0
  9. data/README.rdoc +237 -0
  10. data/Rakefile +4 -0
  11. data/VERSION +1 -0
  12. data/ardm-core.gemspec +25 -0
  13. data/lib/ardm-core.rb +1 -0
  14. data/lib/dm-core.rb +285 -0
  15. data/lib/dm-core/adapters.rb +222 -0
  16. data/lib/dm-core/adapters/abstract_adapter.rb +236 -0
  17. data/lib/dm-core/adapters/in_memory_adapter.rb +113 -0
  18. data/lib/dm-core/associations/many_to_many.rb +496 -0
  19. data/lib/dm-core/associations/many_to_one.rb +296 -0
  20. data/lib/dm-core/associations/one_to_many.rb +345 -0
  21. data/lib/dm-core/associations/one_to_one.rb +86 -0
  22. data/lib/dm-core/associations/relationship.rb +663 -0
  23. data/lib/dm-core/backwards.rb +13 -0
  24. data/lib/dm-core/collection.rb +1514 -0
  25. data/lib/dm-core/core_ext/kernel.rb +23 -0
  26. data/lib/dm-core/core_ext/pathname.rb +6 -0
  27. data/lib/dm-core/core_ext/symbol.rb +10 -0
  28. data/lib/dm-core/identity_map.rb +7 -0
  29. data/lib/dm-core/model.rb +869 -0
  30. data/lib/dm-core/model/hook.rb +102 -0
  31. data/lib/dm-core/model/is.rb +32 -0
  32. data/lib/dm-core/model/property.rb +253 -0
  33. data/lib/dm-core/model/relationship.rb +377 -0
  34. data/lib/dm-core/model/scope.rb +89 -0
  35. data/lib/dm-core/property.rb +839 -0
  36. data/lib/dm-core/property/binary.rb +22 -0
  37. data/lib/dm-core/property/boolean.rb +31 -0
  38. data/lib/dm-core/property/class.rb +24 -0
  39. data/lib/dm-core/property/date.rb +45 -0
  40. data/lib/dm-core/property/date_time.rb +44 -0
  41. data/lib/dm-core/property/decimal.rb +50 -0
  42. data/lib/dm-core/property/discriminator.rb +46 -0
  43. data/lib/dm-core/property/float.rb +28 -0
  44. data/lib/dm-core/property/integer.rb +32 -0
  45. data/lib/dm-core/property/lookup.rb +29 -0
  46. data/lib/dm-core/property/numeric.rb +40 -0
  47. data/lib/dm-core/property/object.rb +28 -0
  48. data/lib/dm-core/property/serial.rb +13 -0
  49. data/lib/dm-core/property/string.rb +50 -0
  50. data/lib/dm-core/property/text.rb +12 -0
  51. data/lib/dm-core/property/time.rb +46 -0
  52. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  53. data/lib/dm-core/property/typecast/time.rb +33 -0
  54. data/lib/dm-core/property_set.rb +177 -0
  55. data/lib/dm-core/query.rb +1444 -0
  56. data/lib/dm-core/query/conditions/comparison.rb +910 -0
  57. data/lib/dm-core/query/conditions/operation.rb +720 -0
  58. data/lib/dm-core/query/direction.rb +36 -0
  59. data/lib/dm-core/query/operator.rb +35 -0
  60. data/lib/dm-core/query/path.rb +114 -0
  61. data/lib/dm-core/query/sort.rb +39 -0
  62. data/lib/dm-core/relationship_set.rb +72 -0
  63. data/lib/dm-core/repository.rb +226 -0
  64. data/lib/dm-core/resource.rb +1228 -0
  65. data/lib/dm-core/resource/persistence_state.rb +75 -0
  66. data/lib/dm-core/resource/persistence_state/clean.rb +40 -0
  67. data/lib/dm-core/resource/persistence_state/deleted.rb +30 -0
  68. data/lib/dm-core/resource/persistence_state/dirty.rb +96 -0
  69. data/lib/dm-core/resource/persistence_state/immutable.rb +34 -0
  70. data/lib/dm-core/resource/persistence_state/persisted.rb +29 -0
  71. data/lib/dm-core/resource/persistence_state/transient.rb +78 -0
  72. data/lib/dm-core/spec/lib/adapter_helpers.rb +54 -0
  73. data/lib/dm-core/spec/lib/collection_helpers.rb +20 -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 +173 -0
  78. data/lib/dm-core/spec/shared/adapter_spec.rb +326 -0
  79. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  80. data/lib/dm-core/spec/shared/resource_spec.rb +1236 -0
  81. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  82. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +134 -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 +402 -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 +12 -0
  102. data/lib/dm-core/support/logger.rb +199 -0
  103. data/lib/dm-core/support/mash.rb +176 -0
  104. data/lib/dm-core/support/naming_conventions.rb +90 -0
  105. data/lib/dm-core/support/ordered_set.rb +380 -0
  106. data/lib/dm-core/support/subject.rb +33 -0
  107. data/lib/dm-core/support/subject_set.rb +250 -0
  108. data/lib/dm-core/version.rb +3 -0
  109. data/script/performance.rb +275 -0
  110. data/script/profile.rb +218 -0
  111. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  112. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +68 -0
  113. data/spec/public/associations/many_to_many_spec.rb +197 -0
  114. data/spec/public/associations/many_to_one_spec.rb +83 -0
  115. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  116. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  117. data/spec/public/associations/one_to_many_spec.rb +81 -0
  118. data/spec/public/associations/one_to_one_spec.rb +176 -0
  119. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  120. data/spec/public/collection_spec.rb +69 -0
  121. data/spec/public/finalize_spec.rb +76 -0
  122. data/spec/public/model/hook_spec.rb +246 -0
  123. data/spec/public/model/property_spec.rb +88 -0
  124. data/spec/public/model/relationship_spec.rb +1040 -0
  125. data/spec/public/model_spec.rb +458 -0
  126. data/spec/public/property/binary_spec.rb +41 -0
  127. data/spec/public/property/boolean_spec.rb +22 -0
  128. data/spec/public/property/class_spec.rb +28 -0
  129. data/spec/public/property/date_spec.rb +22 -0
  130. data/spec/public/property/date_time_spec.rb +22 -0
  131. data/spec/public/property/decimal_spec.rb +23 -0
  132. data/spec/public/property/discriminator_spec.rb +135 -0
  133. data/spec/public/property/float_spec.rb +22 -0
  134. data/spec/public/property/integer_spec.rb +22 -0
  135. data/spec/public/property/object_spec.rb +107 -0
  136. data/spec/public/property/serial_spec.rb +22 -0
  137. data/spec/public/property/string_spec.rb +22 -0
  138. data/spec/public/property/text_spec.rb +63 -0
  139. data/spec/public/property/time_spec.rb +22 -0
  140. data/spec/public/property_spec.rb +341 -0
  141. data/spec/public/resource_spec.rb +284 -0
  142. data/spec/public/sel_spec.rb +53 -0
  143. data/spec/public/setup_spec.rb +145 -0
  144. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  145. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  146. data/spec/public/shared/collection_shared_spec.rb +1669 -0
  147. data/spec/public/shared/finder_shared_spec.rb +1629 -0
  148. data/spec/rcov.opts +6 -0
  149. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  150. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  151. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  152. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  153. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  154. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  155. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  156. data/spec/semipublic/associations_spec.rb +177 -0
  157. data/spec/semipublic/collection_spec.rb +110 -0
  158. data/spec/semipublic/model_spec.rb +96 -0
  159. data/spec/semipublic/property/binary_spec.rb +13 -0
  160. data/spec/semipublic/property/boolean_spec.rb +47 -0
  161. data/spec/semipublic/property/class_spec.rb +33 -0
  162. data/spec/semipublic/property/date_spec.rb +43 -0
  163. data/spec/semipublic/property/date_time_spec.rb +46 -0
  164. data/spec/semipublic/property/decimal_spec.rb +83 -0
  165. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  166. data/spec/semipublic/property/float_spec.rb +82 -0
  167. data/spec/semipublic/property/integer_spec.rb +82 -0
  168. data/spec/semipublic/property/lookup_spec.rb +29 -0
  169. data/spec/semipublic/property/serial_spec.rb +13 -0
  170. data/spec/semipublic/property/string_spec.rb +13 -0
  171. data/spec/semipublic/property/text_spec.rb +31 -0
  172. data/spec/semipublic/property/time_spec.rb +50 -0
  173. data/spec/semipublic/property_spec.rb +114 -0
  174. data/spec/semipublic/query/conditions/comparison_spec.rb +1501 -0
  175. data/spec/semipublic/query/conditions/operation_spec.rb +1294 -0
  176. data/spec/semipublic/query/path_spec.rb +471 -0
  177. data/spec/semipublic/query_spec.rb +3777 -0
  178. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  179. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  180. data/spec/semipublic/resource/state/dirty_spec.rb +156 -0
  181. data/spec/semipublic/resource/state/immutable_spec.rb +105 -0
  182. data/spec/semipublic/resource/state/transient_spec.rb +162 -0
  183. data/spec/semipublic/resource/state_spec.rb +230 -0
  184. data/spec/semipublic/resource_spec.rb +23 -0
  185. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  186. data/spec/semipublic/shared/resource_shared_spec.rb +199 -0
  187. data/spec/semipublic/shared/resource_state_shared_spec.rb +79 -0
  188. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  189. data/spec/spec.opts +5 -0
  190. data/spec/spec_helper.rb +37 -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 +28 -0
  248. data/spec/unit/hook_spec.rb +1235 -0
  249. data/spec/unit/lazy_array_spec.rb +1949 -0
  250. data/spec/unit/mash_spec.rb +312 -0
  251. data/spec/unit/module_spec.rb +71 -0
  252. data/spec/unit/object_spec.rb +38 -0
  253. data/spec/unit/try_dup_spec.rb +46 -0
  254. data/tasks/ci.rake +1 -0
  255. data/tasks/db.rake +11 -0
  256. data/tasks/spec.rake +38 -0
  257. data/tasks/yard.rake +9 -0
  258. data/tasks/yardstick.rake +19 -0
  259. metadata +491 -0
@@ -0,0 +1,458 @@
1
+ require '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 { @article_model.should 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 'should return a Collection' do
52
+ @return.should be_a_kind_of(DataMapper::Collection)
53
+ end
54
+
55
+ it 'should return Resources' do
56
+ @return.each { |resource| resource.should be_a_kind_of(DataMapper::Resource) }
57
+ end
58
+
59
+ it 'should have each Resource set to the expected Repository' do
60
+ @resources.each { |resource| resource.repository.name.should == @adapter.name }
61
+ end
62
+
63
+ it 'should create the Resources in the expected Repository' do
64
+ @article_model.all(:repository => DataMapper.repository(@adapter.name)).should == @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
+ @article_model.all(:repository => @repository).should 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 'should return a Collection' do
97
+ @return.should be_a_kind_of(DataMapper::Collection)
98
+ end
99
+
100
+ it 'should return Resources' do
101
+ @return.each { |resource| resource.should be_a_kind_of(DataMapper::Resource) }
102
+ end
103
+
104
+ it 'should have each Resource set to the expected Repository' do
105
+ @resources.each { |resource| resource.repository.name.should == :default }
106
+ end
107
+
108
+ it 'should return the expected resources' do
109
+ # match on id because resources from different repositories are different
110
+ @resources.map { |resource| resource.id }.should == [ @heff1.id ]
111
+ end
112
+
113
+ it 'should add the resources to the alternate repository' do
114
+ @article.model.get(*@heff1.key).should_not 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 { should be_instance_of(model) }
181
+
182
+ its(:attributes) { should == { :title => 'Default Title' } }
183
+ end
184
+
185
+ context 'with an empty Hash' do
186
+ let(:args) { [ {} ] }
187
+
188
+ it { should be_instance_of(model) }
189
+
190
+ its(:attributes) { should == { :title => 'Default Title' } }
191
+ end
192
+
193
+ context 'with a non-empty Hash' do
194
+ let(:attributes) { { :title => 'A Title' } }
195
+ let(:args) { [ attributes ] }
196
+
197
+ it { should be_instance_of(model) }
198
+
199
+ its(:attributes) { should == attributes }
200
+ end
201
+
202
+ context 'with nil' do
203
+ let(:args) { [ nil ] }
204
+
205
+ it { should be_instance_of(model) }
206
+
207
+ its(:attributes) { should == { :title => 'Default Title' } }
208
+ end
209
+ end
210
+
211
+ [ :create, :create! ].each do |method|
212
+ describe "##{method}" do
213
+ subject { model.send(method, *args) }
214
+
215
+ let(:model) { @article_model }
216
+
217
+ context 'with no arguments' do
218
+ let(:args) { [] }
219
+
220
+ it { should be_instance_of(model) }
221
+
222
+ it { should be_saved }
223
+ end
224
+
225
+ context 'with an empty Hash' do
226
+ let(:args) { [ {} ] }
227
+
228
+ it { should be_instance_of(model) }
229
+
230
+ it { should be_saved }
231
+ end
232
+
233
+ context 'with a non-empty Hash' do
234
+ let(:attributes) { { :title => 'A Title' } }
235
+ let(:args) { [ attributes ] }
236
+
237
+ it { should be_instance_of(model) }
238
+
239
+ it { should be_saved }
240
+
241
+ its(:title) { should == attributes[:title] }
242
+ end
243
+
244
+ context 'with nil' do
245
+ let(:args) { [ nil ] }
246
+
247
+ it { should be_instance_of(model) }
248
+
249
+ it { should be_saved }
250
+ end
251
+ end
252
+ end
253
+
254
+ [ :destroy, :destroy! ].each do |method|
255
+ describe "##{method}" do
256
+ subject { model.send(method) }
257
+
258
+ let(:model) { @article_model }
259
+
260
+ it 'should remove all resources' do
261
+ method(:subject).should change { model.any? }.from(true).to(false)
262
+ end
263
+ end
264
+ end
265
+
266
+ [ :update, :update! ].each do |method|
267
+ describe "##{method}" do
268
+ subject { model.send(method, *args) }
269
+
270
+ let(:model) { @article_model }
271
+
272
+ context 'with attributes' do
273
+ let(:attributes) { { :title => 'Updated Title' } }
274
+ let(:args) { [ attributes ] }
275
+
276
+ it { should be(true) }
277
+
278
+ it 'should persist the changes' do
279
+ subject
280
+ model.all(:fields => [ :title ]).map { |resource| resource.title }.uniq.should == [ attributes[:title] ]
281
+ end
282
+ end
283
+
284
+ context 'with attributes where one is a parent association' do
285
+ let(:attributes) { { :original => @other } }
286
+ let(:args) { [ attributes ] }
287
+
288
+ it { should be(true) }
289
+
290
+ it 'should persist the changes' do
291
+ subject
292
+ model.all(:fields => [ :original_id ]).map { |resource| resource.original }.uniq.should == [ attributes[:original] ]
293
+ end
294
+ end
295
+
296
+ context 'with attributes where a required property is nil' do
297
+ let(:attributes) { { :title => nil } }
298
+ let(:args) { [ attributes ] }
299
+
300
+ it { should be(false) }
301
+ end
302
+ end
303
+ end
304
+
305
+ it_should_behave_like 'Finder Interface'
306
+
307
+ it 'DataMapper::Model should respond to raise_on_save_failure' do
308
+ DataMapper::Model.should 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 { should be(false) }
315
+ end
316
+
317
+ it 'DataMapper::Model should respond to raise_on_save_failure=' do
318
+ DataMapper::Model.should 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 { should be(true) }
335
+
336
+ it 'should set raise_on_save_failure' do
337
+ method(:subject).should 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 { should be(false) }
349
+
350
+ it 'should set raise_on_save_failure' do
351
+ method(:subject).should_not change {
352
+ DataMapper::Model.raise_on_save_failure
353
+ }
354
+ end
355
+ end
356
+ end
357
+
358
+ it 'A model should respond to raise_on_save_failure' do
359
+ @article_model.should 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 { should 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 { should 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 { should be(true) }
389
+ end
390
+ end
391
+
392
+ it 'A model should respond to raise_on_save_failure=' do
393
+ @article_model.should 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 { should be(true) }
410
+
411
+ it 'should set raise_on_save_failure' do
412
+ method(:subject).should 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 { should be(false) }
424
+
425
+ it 'should set raise_on_save_failure' do
426
+ method(:subject).should_not change {
427
+ @article_model.raise_on_save_failure
428
+ }
429
+ end
430
+ end
431
+ end
432
+
433
+ it 'A model should respond to allowed_writer_methods' do
434
+ @article_model.should 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 { should be_kind_of(Set) }
446
+
447
+ it { should be_all { |method| method.kind_of?(String) } }
448
+
449
+ it { should be_frozen }
450
+
451
+ it 'is idempotent' do
452
+ should equal(instance_eval(&self.class.subject))
453
+ end
454
+
455
+ it { should eql(expected_writer_methods) }
456
+ end
457
+ end
458
+ end