ghost_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 (254) hide show
  1. data/.autotest +29 -0
  2. data/.document +5 -0
  3. data/.gitignore +35 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +65 -0
  6. data/LICENSE +20 -0
  7. data/README.md +269 -0
  8. data/Rakefile +4 -0
  9. data/dm-core.gemspec +24 -0
  10. data/lib/dm-core.rb +292 -0
  11. data/lib/dm-core/adapters.rb +222 -0
  12. data/lib/dm-core/adapters/abstract_adapter.rb +237 -0
  13. data/lib/dm-core/adapters/in_memory_adapter.rb +113 -0
  14. data/lib/dm-core/associations/many_to_many.rb +499 -0
  15. data/lib/dm-core/associations/many_to_one.rb +290 -0
  16. data/lib/dm-core/associations/one_to_many.rb +348 -0
  17. data/lib/dm-core/associations/one_to_one.rb +86 -0
  18. data/lib/dm-core/associations/relationship.rb +663 -0
  19. data/lib/dm-core/backwards.rb +13 -0
  20. data/lib/dm-core/collection.rb +1515 -0
  21. data/lib/dm-core/core_ext/kernel.rb +23 -0
  22. data/lib/dm-core/core_ext/pathname.rb +6 -0
  23. data/lib/dm-core/core_ext/symbol.rb +10 -0
  24. data/lib/dm-core/identity_map.rb +7 -0
  25. data/lib/dm-core/model.rb +874 -0
  26. data/lib/dm-core/model/hook.rb +103 -0
  27. data/lib/dm-core/model/is.rb +32 -0
  28. data/lib/dm-core/model/property.rb +249 -0
  29. data/lib/dm-core/model/relationship.rb +378 -0
  30. data/lib/dm-core/model/scope.rb +89 -0
  31. data/lib/dm-core/property.rb +866 -0
  32. data/lib/dm-core/property/binary.rb +21 -0
  33. data/lib/dm-core/property/boolean.rb +20 -0
  34. data/lib/dm-core/property/class.rb +17 -0
  35. data/lib/dm-core/property/date.rb +10 -0
  36. data/lib/dm-core/property/date_time.rb +10 -0
  37. data/lib/dm-core/property/decimal.rb +36 -0
  38. data/lib/dm-core/property/discriminator.rb +44 -0
  39. data/lib/dm-core/property/float.rb +16 -0
  40. data/lib/dm-core/property/integer.rb +22 -0
  41. data/lib/dm-core/property/invalid_value_error.rb +22 -0
  42. data/lib/dm-core/property/lookup.rb +27 -0
  43. data/lib/dm-core/property/numeric.rb +38 -0
  44. data/lib/dm-core/property/object.rb +34 -0
  45. data/lib/dm-core/property/serial.rb +14 -0
  46. data/lib/dm-core/property/string.rb +38 -0
  47. data/lib/dm-core/property/text.rb +9 -0
  48. data/lib/dm-core/property/time.rb +10 -0
  49. data/lib/dm-core/property_set.rb +177 -0
  50. data/lib/dm-core/query.rb +1366 -0
  51. data/lib/dm-core/query/conditions/comparison.rb +911 -0
  52. data/lib/dm-core/query/conditions/operation.rb +721 -0
  53. data/lib/dm-core/query/direction.rb +36 -0
  54. data/lib/dm-core/query/operator.rb +35 -0
  55. data/lib/dm-core/query/path.rb +114 -0
  56. data/lib/dm-core/query/sort.rb +39 -0
  57. data/lib/dm-core/relationship_set.rb +72 -0
  58. data/lib/dm-core/repository.rb +226 -0
  59. data/lib/dm-core/resource.rb +1214 -0
  60. data/lib/dm-core/resource/persistence_state.rb +75 -0
  61. data/lib/dm-core/resource/persistence_state/clean.rb +40 -0
  62. data/lib/dm-core/resource/persistence_state/deleted.rb +30 -0
  63. data/lib/dm-core/resource/persistence_state/dirty.rb +96 -0
  64. data/lib/dm-core/resource/persistence_state/immutable.rb +34 -0
  65. data/lib/dm-core/resource/persistence_state/persisted.rb +29 -0
  66. data/lib/dm-core/resource/persistence_state/transient.rb +80 -0
  67. data/lib/dm-core/spec/lib/adapter_helpers.rb +64 -0
  68. data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
  69. data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
  70. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  71. data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
  72. data/lib/dm-core/spec/setup.rb +174 -0
  73. data/lib/dm-core/spec/shared/adapter_spec.rb +341 -0
  74. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  75. data/lib/dm-core/spec/shared/resource_spec.rb +1232 -0
  76. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  77. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +176 -0
  78. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  79. data/lib/dm-core/support/assertions.rb +8 -0
  80. data/lib/dm-core/support/chainable.rb +18 -0
  81. data/lib/dm-core/support/deprecate.rb +12 -0
  82. data/lib/dm-core/support/descendant_set.rb +89 -0
  83. data/lib/dm-core/support/equalizer.rb +48 -0
  84. data/lib/dm-core/support/ext/array.rb +22 -0
  85. data/lib/dm-core/support/ext/blank.rb +25 -0
  86. data/lib/dm-core/support/ext/hash.rb +67 -0
  87. data/lib/dm-core/support/ext/module.rb +47 -0
  88. data/lib/dm-core/support/ext/object.rb +57 -0
  89. data/lib/dm-core/support/ext/string.rb +24 -0
  90. data/lib/dm-core/support/ext/try_dup.rb +12 -0
  91. data/lib/dm-core/support/hook.rb +405 -0
  92. data/lib/dm-core/support/inflections.rb +60 -0
  93. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  94. data/lib/dm-core/support/inflector/methods.rb +151 -0
  95. data/lib/dm-core/support/lazy_array.rb +451 -0
  96. data/lib/dm-core/support/local_object_space.rb +13 -0
  97. data/lib/dm-core/support/logger.rb +201 -0
  98. data/lib/dm-core/support/mash.rb +176 -0
  99. data/lib/dm-core/support/naming_conventions.rb +90 -0
  100. data/lib/dm-core/support/ordered_set.rb +380 -0
  101. data/lib/dm-core/support/subject.rb +33 -0
  102. data/lib/dm-core/support/subject_set.rb +250 -0
  103. data/lib/dm-core/version.rb +3 -0
  104. data/script/performance.rb +275 -0
  105. data/script/profile.rb +218 -0
  106. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  107. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +68 -0
  108. data/spec/public/associations/many_to_many_spec.rb +197 -0
  109. data/spec/public/associations/many_to_one_spec.rb +83 -0
  110. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  111. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  112. data/spec/public/associations/one_to_many_spec.rb +81 -0
  113. data/spec/public/associations/one_to_one_spec.rb +176 -0
  114. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  115. data/spec/public/collection_spec.rb +69 -0
  116. data/spec/public/finalize_spec.rb +76 -0
  117. data/spec/public/model/hook_spec.rb +246 -0
  118. data/spec/public/model/property_spec.rb +88 -0
  119. data/spec/public/model/relationship_spec.rb +1040 -0
  120. data/spec/public/model_spec.rb +462 -0
  121. data/spec/public/property/binary_spec.rb +41 -0
  122. data/spec/public/property/boolean_spec.rb +22 -0
  123. data/spec/public/property/class_spec.rb +28 -0
  124. data/spec/public/property/date_spec.rb +22 -0
  125. data/spec/public/property/date_time_spec.rb +22 -0
  126. data/spec/public/property/decimal_spec.rb +23 -0
  127. data/spec/public/property/discriminator_spec.rb +135 -0
  128. data/spec/public/property/float_spec.rb +22 -0
  129. data/spec/public/property/integer_spec.rb +22 -0
  130. data/spec/public/property/object_spec.rb +107 -0
  131. data/spec/public/property/serial_spec.rb +22 -0
  132. data/spec/public/property/string_spec.rb +22 -0
  133. data/spec/public/property/text_spec.rb +63 -0
  134. data/spec/public/property/time_spec.rb +22 -0
  135. data/spec/public/property_spec.rb +341 -0
  136. data/spec/public/resource_spec.rb +288 -0
  137. data/spec/public/sel_spec.rb +53 -0
  138. data/spec/public/setup_spec.rb +145 -0
  139. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  140. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  141. data/spec/public/shared/collection_shared_spec.rb +1667 -0
  142. data/spec/public/shared/finder_shared_spec.rb +1629 -0
  143. data/spec/rcov.opts +6 -0
  144. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  145. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
  146. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  147. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  148. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  149. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  150. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  151. data/spec/semipublic/associations_spec.rb +177 -0
  152. data/spec/semipublic/collection_spec.rb +110 -0
  153. data/spec/semipublic/model_spec.rb +96 -0
  154. data/spec/semipublic/property/binary_spec.rb +13 -0
  155. data/spec/semipublic/property/boolean_spec.rb +47 -0
  156. data/spec/semipublic/property/class_spec.rb +33 -0
  157. data/spec/semipublic/property/date_spec.rb +43 -0
  158. data/spec/semipublic/property/date_time_spec.rb +46 -0
  159. data/spec/semipublic/property/decimal_spec.rb +83 -0
  160. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  161. data/spec/semipublic/property/float_spec.rb +82 -0
  162. data/spec/semipublic/property/integer_spec.rb +82 -0
  163. data/spec/semipublic/property/lookup_spec.rb +29 -0
  164. data/spec/semipublic/property/serial_spec.rb +13 -0
  165. data/spec/semipublic/property/string_spec.rb +13 -0
  166. data/spec/semipublic/property/text_spec.rb +31 -0
  167. data/spec/semipublic/property/time_spec.rb +50 -0
  168. data/spec/semipublic/property_spec.rb +114 -0
  169. data/spec/semipublic/query/conditions/comparison_spec.rb +1501 -0
  170. data/spec/semipublic/query/conditions/operation_spec.rb +1294 -0
  171. data/spec/semipublic/query/path_spec.rb +471 -0
  172. data/spec/semipublic/query_spec.rb +3682 -0
  173. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  174. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  175. data/spec/semipublic/resource/state/dirty_spec.rb +162 -0
  176. data/spec/semipublic/resource/state/immutable_spec.rb +105 -0
  177. data/spec/semipublic/resource/state/transient_spec.rb +162 -0
  178. data/spec/semipublic/resource/state_spec.rb +230 -0
  179. data/spec/semipublic/resource_spec.rb +23 -0
  180. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  181. data/spec/semipublic/shared/resource_shared_spec.rb +199 -0
  182. data/spec/semipublic/shared/resource_state_shared_spec.rb +79 -0
  183. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  184. data/spec/spec.opts +5 -0
  185. data/spec/spec_helper.rb +38 -0
  186. data/spec/support/core_ext/hash.rb +10 -0
  187. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  188. data/spec/support/properties/huge_integer.rb +17 -0
  189. data/spec/unit/array_spec.rb +23 -0
  190. data/spec/unit/blank_spec.rb +73 -0
  191. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  192. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  193. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  194. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  195. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  196. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  197. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  198. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  199. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  200. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  201. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  202. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  203. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  204. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  205. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  206. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  207. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  208. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  209. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  210. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  211. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  212. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  213. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  214. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  215. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  216. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  217. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  218. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  219. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  220. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  221. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  222. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  223. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  224. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  225. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  226. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  227. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  228. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  229. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  230. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  231. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  232. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  233. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  234. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  235. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  236. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  237. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  238. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  239. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  240. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  241. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  242. data/spec/unit/hash_spec.rb +28 -0
  243. data/spec/unit/hook_spec.rb +1235 -0
  244. data/spec/unit/inflections_spec.rb +16 -0
  245. data/spec/unit/lazy_array_spec.rb +1949 -0
  246. data/spec/unit/mash_spec.rb +312 -0
  247. data/spec/unit/module_spec.rb +71 -0
  248. data/spec/unit/object_spec.rb +38 -0
  249. data/spec/unit/try_dup_spec.rb +46 -0
  250. data/tasks/ci.rake +1 -0
  251. data/tasks/spec.rake +38 -0
  252. data/tasks/yard.rake +9 -0
  253. data/tasks/yardstick.rake +19 -0
  254. metadata +365 -0
@@ -0,0 +1,462 @@
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 raise InvalidValueError' do
301
+ expect { subject }.to(raise_error(DataMapper::Property::InvalidValueError) do |error|
302
+ error.property.should == model.title
303
+ end)
304
+ end
305
+ end
306
+ end
307
+ end
308
+
309
+ it_should_behave_like 'Finder Interface'
310
+
311
+ it 'DataMapper::Model should respond to raise_on_save_failure' do
312
+ DataMapper::Model.should respond_to(:raise_on_save_failure)
313
+ end
314
+
315
+ describe '.raise_on_save_failure' do
316
+ subject { DataMapper::Model.raise_on_save_failure }
317
+
318
+ it { should be(false) }
319
+ end
320
+
321
+ it 'DataMapper::Model should respond to raise_on_save_failure=' do
322
+ DataMapper::Model.should respond_to(:raise_on_save_failure=)
323
+ end
324
+
325
+ describe '.raise_on_save_failure=' do
326
+ after do
327
+ # reset to the default value
328
+ reset_raise_on_save_failure(DataMapper::Model)
329
+ end
330
+
331
+ subject { DataMapper::Model.raise_on_save_failure = @value }
332
+
333
+ describe 'with a true value' do
334
+ before do
335
+ @value = true
336
+ end
337
+
338
+ it { should be(true) }
339
+
340
+ it 'should set raise_on_save_failure' do
341
+ method(:subject).should change {
342
+ DataMapper::Model.raise_on_save_failure
343
+ }.from(false).to(true)
344
+ end
345
+ end
346
+
347
+ describe 'with a false value' do
348
+ before do
349
+ @value = false
350
+ end
351
+
352
+ it { should be(false) }
353
+
354
+ it 'should set raise_on_save_failure' do
355
+ method(:subject).should_not change {
356
+ DataMapper::Model.raise_on_save_failure
357
+ }
358
+ end
359
+ end
360
+ end
361
+
362
+ it 'A model should respond to raise_on_save_failure' do
363
+ @article_model.should respond_to(:raise_on_save_failure)
364
+ end
365
+
366
+ describe '#raise_on_save_failure' do
367
+ after do
368
+ # reset to the default value
369
+ reset_raise_on_save_failure(DataMapper::Model)
370
+ reset_raise_on_save_failure(@article_model)
371
+ end
372
+
373
+ subject { @article_model.raise_on_save_failure }
374
+
375
+ describe 'when DataMapper::Model.raise_on_save_failure has not been set' do
376
+ it { should be(false) }
377
+ end
378
+
379
+ describe 'when DataMapper::Model.raise_on_save_failure has been set to true' do
380
+ before do
381
+ DataMapper::Model.raise_on_save_failure = true
382
+ end
383
+
384
+ it { should be(true) }
385
+ end
386
+
387
+ describe 'when model.raise_on_save_failure has been set to true' do
388
+ before do
389
+ @article_model.raise_on_save_failure = true
390
+ end
391
+
392
+ it { should be(true) }
393
+ end
394
+ end
395
+
396
+ it 'A model should respond to raise_on_save_failure=' do
397
+ @article_model.should respond_to(:raise_on_save_failure=)
398
+ end
399
+
400
+ describe '#raise_on_save_failure=' do
401
+ after do
402
+ # reset to the default value
403
+ reset_raise_on_save_failure(@article_model)
404
+ end
405
+
406
+ subject { @article_model.raise_on_save_failure = @value }
407
+
408
+ describe 'with a true value' do
409
+ before do
410
+ @value = true
411
+ end
412
+
413
+ it { should be(true) }
414
+
415
+ it 'should set raise_on_save_failure' do
416
+ method(:subject).should change {
417
+ @article_model.raise_on_save_failure
418
+ }.from(false).to(true)
419
+ end
420
+ end
421
+
422
+ describe 'with a false value' do
423
+ before do
424
+ @value = false
425
+ end
426
+
427
+ it { should be(false) }
428
+
429
+ it 'should set raise_on_save_failure' do
430
+ method(:subject).should_not change {
431
+ @article_model.raise_on_save_failure
432
+ }
433
+ end
434
+ end
435
+ end
436
+
437
+ it 'A model should respond to allowed_writer_methods' do
438
+ @article_model.should respond_to(:allowed_writer_methods)
439
+ end
440
+
441
+ describe '#allowed_writer_methods' do
442
+ subject { @article_model.allowed_writer_methods }
443
+
444
+ let(:expected_writer_methods) do
445
+ %w[ original= revisions= previous= publications= article_publications=
446
+ id= title= content= subtitle= original_id= persisted_state= ].to_set
447
+ end
448
+
449
+ it { should be_kind_of(Set) }
450
+
451
+ it { should be_all { |method| method.kind_of?(String) } }
452
+
453
+ it { should be_frozen }
454
+
455
+ it 'is idempotent' do
456
+ should equal(instance_eval(&self.class.subject))
457
+ end
458
+
459
+ it { should eql(expected_writer_methods) }
460
+ end
461
+ end
462
+ end