dm-core 0.10.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. data/.gitignore +10 -1
  2. data/Gemfile +143 -0
  3. data/Rakefile +9 -5
  4. data/VERSION +1 -1
  5. data/dm-core.gemspec +160 -57
  6. data/lib/dm-core.rb +131 -56
  7. data/lib/dm-core/adapters.rb +98 -14
  8. data/lib/dm-core/adapters/abstract_adapter.rb +24 -4
  9. data/lib/dm-core/adapters/in_memory_adapter.rb +7 -2
  10. data/lib/dm-core/associations/many_to_many.rb +19 -30
  11. data/lib/dm-core/associations/many_to_one.rb +58 -42
  12. data/lib/dm-core/associations/one_to_many.rb +33 -23
  13. data/lib/dm-core/associations/one_to_one.rb +27 -11
  14. data/lib/dm-core/associations/relationship.rb +4 -4
  15. data/lib/dm-core/collection.rb +23 -16
  16. data/lib/dm-core/core_ext/array.rb +36 -0
  17. data/lib/dm-core/core_ext/hash.rb +30 -0
  18. data/lib/dm-core/core_ext/module.rb +46 -0
  19. data/lib/dm-core/core_ext/object.rb +31 -0
  20. data/lib/dm-core/core_ext/pathname.rb +20 -0
  21. data/lib/dm-core/core_ext/string.rb +22 -0
  22. data/lib/dm-core/core_ext/try_dup.rb +44 -0
  23. data/lib/dm-core/model.rb +88 -27
  24. data/lib/dm-core/model/hook.rb +75 -18
  25. data/lib/dm-core/model/property.rb +50 -9
  26. data/lib/dm-core/model/relationship.rb +31 -31
  27. data/lib/dm-core/model/scope.rb +3 -3
  28. data/lib/dm-core/property.rb +196 -516
  29. data/lib/dm-core/property/binary.rb +7 -0
  30. data/lib/dm-core/property/boolean.rb +35 -0
  31. data/lib/dm-core/property/class.rb +24 -0
  32. data/lib/dm-core/property/date.rb +47 -0
  33. data/lib/dm-core/property/date_time.rb +48 -0
  34. data/lib/dm-core/property/decimal.rb +43 -0
  35. data/lib/dm-core/property/discriminator.rb +48 -0
  36. data/lib/dm-core/property/float.rb +24 -0
  37. data/lib/dm-core/property/integer.rb +32 -0
  38. data/lib/dm-core/property/numeric.rb +43 -0
  39. data/lib/dm-core/property/object.rb +32 -0
  40. data/lib/dm-core/property/serial.rb +8 -0
  41. data/lib/dm-core/property/string.rb +49 -0
  42. data/lib/dm-core/property/text.rb +12 -0
  43. data/lib/dm-core/property/time.rb +48 -0
  44. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  45. data/lib/dm-core/property/typecast/time.rb +28 -0
  46. data/lib/dm-core/property_set.rb +10 -4
  47. data/lib/dm-core/query.rb +14 -37
  48. data/lib/dm-core/query/conditions/comparison.rb +8 -6
  49. data/lib/dm-core/query/conditions/operation.rb +33 -2
  50. data/lib/dm-core/query/operator.rb +2 -5
  51. data/lib/dm-core/query/path.rb +4 -6
  52. data/lib/dm-core/repository.rb +21 -6
  53. data/lib/dm-core/resource.rb +316 -133
  54. data/lib/dm-core/resource/state.rb +79 -0
  55. data/lib/dm-core/resource/state/clean.rb +40 -0
  56. data/lib/dm-core/resource/state/deleted.rb +30 -0
  57. data/lib/dm-core/resource/state/dirty.rb +86 -0
  58. data/lib/dm-core/resource/state/immutable.rb +34 -0
  59. data/lib/dm-core/resource/state/persisted.rb +29 -0
  60. data/lib/dm-core/resource/state/transient.rb +70 -0
  61. data/lib/dm-core/spec/lib/adapter_helpers.rb +52 -0
  62. data/lib/dm-core/spec/lib/collection_helpers.rb +20 -0
  63. data/{spec → lib/dm-core/spec}/lib/counter_adapter.rb +5 -1
  64. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  65. data/lib/dm-core/spec/lib/spec_helper.rb +68 -0
  66. data/lib/dm-core/spec/setup.rb +165 -0
  67. data/lib/dm-core/spec/{adapter_shared_spec.rb → shared/adapter_spec.rb} +21 -7
  68. data/{spec/public/shared/resource_shared_spec.rb → lib/dm-core/spec/shared/resource_spec.rb} +120 -83
  69. data/{spec/public/shared/sel_shared_spec.rb → lib/dm-core/spec/shared/sel_spec.rb} +5 -6
  70. data/lib/dm-core/support/assertions.rb +8 -0
  71. data/lib/dm-core/support/equalizer.rb +1 -0
  72. data/lib/dm-core/support/hook.rb +420 -0
  73. data/lib/dm-core/support/lazy_array.rb +453 -0
  74. data/lib/dm-core/support/local_object_space.rb +12 -0
  75. data/lib/dm-core/support/logger.rb +193 -6
  76. data/lib/dm-core/support/naming_conventions.rb +8 -8
  77. data/lib/dm-core/support/subject.rb +33 -0
  78. data/lib/dm-core/type.rb +4 -0
  79. data/lib/dm-core/types/boolean.rb +2 -0
  80. data/lib/dm-core/types/decimal.rb +9 -0
  81. data/lib/dm-core/types/discriminator.rb +2 -0
  82. data/lib/dm-core/types/object.rb +3 -0
  83. data/lib/dm-core/types/serial.rb +2 -0
  84. data/lib/dm-core/types/text.rb +2 -0
  85. data/lib/dm-core/version.rb +1 -1
  86. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +67 -0
  87. data/spec/public/model/hook_spec.rb +209 -0
  88. data/spec/public/model/property_spec.rb +35 -0
  89. data/spec/public/model/relationship_spec.rb +33 -20
  90. data/spec/public/model_spec.rb +142 -10
  91. data/spec/public/property/binary_spec.rb +14 -0
  92. data/spec/public/property/boolean_spec.rb +14 -0
  93. data/spec/public/property/class_spec.rb +20 -0
  94. data/spec/public/property/date_spec.rb +14 -0
  95. data/spec/public/property/date_time_spec.rb +14 -0
  96. data/spec/public/property/decimal_spec.rb +14 -0
  97. data/spec/public/{types → property}/discriminator_spec.rb +2 -12
  98. data/spec/public/property/float_spec.rb +14 -0
  99. data/spec/public/property/integer_spec.rb +14 -0
  100. data/spec/public/property/object_spec.rb +9 -17
  101. data/spec/public/property/serial_spec.rb +14 -0
  102. data/spec/public/property/string_spec.rb +14 -0
  103. data/spec/public/property/text_spec.rb +52 -0
  104. data/spec/public/property/time_spec.rb +14 -0
  105. data/spec/public/property_spec.rb +28 -87
  106. data/spec/public/resource_spec.rb +101 -0
  107. data/spec/public/sel_spec.rb +5 -15
  108. data/spec/public/shared/collection_shared_spec.rb +16 -30
  109. data/spec/public/shared/finder_shared_spec.rb +2 -4
  110. data/spec/public/shared/property_shared_spec.rb +176 -0
  111. data/spec/semipublic/adapters/abstract_adapter_spec.rb +1 -1
  112. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +2 -2
  113. data/spec/semipublic/associations/many_to_many_spec.rb +89 -0
  114. data/spec/semipublic/associations/many_to_one_spec.rb +24 -1
  115. data/spec/semipublic/associations/one_to_many_spec.rb +51 -0
  116. data/spec/semipublic/associations/one_to_one_spec.rb +49 -0
  117. data/spec/semipublic/associations/relationship_spec.rb +3 -3
  118. data/spec/semipublic/associations_spec.rb +1 -1
  119. data/spec/semipublic/property/binary_spec.rb +13 -0
  120. data/spec/semipublic/property/boolean_spec.rb +65 -0
  121. data/spec/semipublic/property/class_spec.rb +33 -0
  122. data/spec/semipublic/property/date_spec.rb +43 -0
  123. data/spec/semipublic/property/date_time_spec.rb +46 -0
  124. data/spec/semipublic/property/decimal_spec.rb +82 -0
  125. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  126. data/spec/semipublic/property/float_spec.rb +82 -0
  127. data/spec/semipublic/property/integer_spec.rb +82 -0
  128. data/spec/semipublic/property/serial_spec.rb +13 -0
  129. data/spec/semipublic/property/string_spec.rb +13 -0
  130. data/spec/semipublic/property/text_spec.rb +31 -0
  131. data/spec/semipublic/property/time_spec.rb +50 -0
  132. data/spec/semipublic/property_spec.rb +2 -532
  133. data/spec/semipublic/query/conditions/comparison_spec.rb +171 -169
  134. data/spec/semipublic/query/conditions/operation_spec.rb +53 -51
  135. data/spec/semipublic/query/path_spec.rb +17 -17
  136. data/spec/semipublic/query_spec.rb +47 -78
  137. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  138. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  139. data/spec/semipublic/resource/state/dirty_spec.rb +133 -0
  140. data/spec/semipublic/resource/state/immutable_spec.rb +99 -0
  141. data/spec/semipublic/resource/state/transient_spec.rb +128 -0
  142. data/spec/semipublic/resource/state_spec.rb +226 -0
  143. data/spec/semipublic/shared/property_shared_spec.rb +143 -0
  144. data/spec/semipublic/shared/resource_shared_spec.rb +16 -15
  145. data/spec/semipublic/shared/resource_state_shared_spec.rb +78 -0
  146. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  147. data/spec/spec_helper.rb +21 -97
  148. data/spec/support/types/huge_integer.rb +17 -0
  149. data/spec/unit/array_spec.rb +48 -0
  150. data/spec/unit/hash_spec.rb +35 -0
  151. data/spec/unit/hook_spec.rb +1234 -0
  152. data/spec/unit/lazy_array_spec.rb +1959 -0
  153. data/spec/unit/module_spec.rb +70 -0
  154. data/spec/unit/object_spec.rb +37 -0
  155. data/spec/unit/try_dup_spec.rb +45 -0
  156. data/tasks/local_gemfile.rake +18 -0
  157. data/tasks/spec.rake +0 -3
  158. metadata +197 -71
  159. data/deps.rip +0 -2
  160. data/lib/dm-core/adapters/data_objects_adapter.rb +0 -712
  161. data/lib/dm-core/adapters/mysql_adapter.rb +0 -42
  162. data/lib/dm-core/adapters/oracle_adapter.rb +0 -229
  163. data/lib/dm-core/adapters/postgres_adapter.rb +0 -22
  164. data/lib/dm-core/adapters/sqlite3_adapter.rb +0 -17
  165. data/lib/dm-core/adapters/sqlserver_adapter.rb +0 -114
  166. data/lib/dm-core/adapters/yaml_adapter.rb +0 -111
  167. data/lib/dm-core/core_ext/enumerable.rb +0 -28
  168. data/lib/dm-core/migrations.rb +0 -1427
  169. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +0 -366
  170. data/lib/dm-core/transaction.rb +0 -508
  171. data/lib/dm-core/types/paranoid_boolean.rb +0 -42
  172. data/lib/dm-core/types/paranoid_datetime.rb +0 -41
  173. data/spec/lib/adapter_helpers.rb +0 -105
  174. data/spec/lib/collection_helpers.rb +0 -18
  175. data/spec/lib/pending_helpers.rb +0 -46
  176. data/spec/public/migrations_spec.rb +0 -503
  177. data/spec/public/transaction_spec.rb +0 -153
  178. data/spec/semipublic/adapters/mysql_adapter_spec.rb +0 -17
  179. data/spec/semipublic/adapters/oracle_adapter_spec.rb +0 -194
  180. data/spec/semipublic/adapters/postgres_adapter_spec.rb +0 -17
  181. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +0 -17
  182. data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +0 -17
  183. data/spec/semipublic/adapters/yaml_adapter_spec.rb +0 -12
@@ -1,5 +1,9 @@
1
1
  class CounterAdapter < DataMapper::Adapters::AbstractAdapter
2
- instance_methods.each { |method| undef_method method unless %w[ __id__ __send__ send class dup object_id kind_of? instance_of? respond_to? equal? assert_kind_of should should_not instance_variable_set instance_variable_get extend ].include?(method.to_s) }
2
+ instance_methods.each do |method|
3
+ next if method =~ /\A__/ ||
4
+ %w[ send class dup object_id kind_of? instance_of? respond_to? equal? freeze frozen? should should_not instance_variables instance_variable_set instance_variable_get instance_variable_defined? remove_instance_variable extend hash inspect copy_object ].include?(method.to_s)
5
+ undef_method method
6
+ end
3
7
 
4
8
  attr_reader :counts
5
9
 
@@ -0,0 +1,50 @@
1
+ module DataMapper
2
+ module Spec
3
+ module PendingHelpers
4
+
5
+ def pending_if(*args)
6
+ message, boolean = parse_args(*args)
7
+
8
+ if boolean
9
+ pending(message) { yield }
10
+ else
11
+ yield
12
+ end
13
+ end
14
+
15
+ def rescue_if(*args)
16
+ message, boolean = parse_args(*args)
17
+
18
+ if boolean
19
+ raised = nil
20
+ begin
21
+ yield
22
+ raised = false
23
+ rescue Exception
24
+ raised = true
25
+ end
26
+
27
+ raise "should have raised: #{message || 'TODO'}" if raised == false
28
+ else
29
+ yield
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def parse_args(*args)
36
+ case args.map { |arg| arg.class }
37
+ when [ String, TrueClass ], [ String, FalseClass ] then args
38
+ when [ String, NilClass ] then [ args.first, false ]
39
+ when [ String ] then [ args.first, true ]
40
+ when [ TrueClass ], [ FalseClass ] then [ '', args.first ]
41
+ when [ NilClass ] then [ '', false ]
42
+ when [] then [ '', true ] # defaults
43
+ else
44
+ raise ArgumentError, "Invalid arguments: #{args.inspect}"
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,68 @@
1
+ module DataMapper
2
+ module Spec
3
+
4
+ module Helpers
5
+ def reset_raise_on_save_failure(object)
6
+ object.instance_eval do
7
+ if defined?(@raise_on_save_failure)
8
+ remove_instance_variable(:@raise_on_save_failure)
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ # global model cleanup
15
+ def self.cleanup_models
16
+ descendants = DataMapper::Model.descendants.to_a
17
+ while model = descendants.shift
18
+ descendants.concat(model.descendants.to_a - [ model ])
19
+
20
+ unless model.name.to_s[0] == ?#
21
+ parts = model.name.split('::')
22
+ constant_name = parts.pop.to_sym
23
+ base = parts.empty? ? Object : Object.full_const_get(parts.join('::'))
24
+
25
+ base.class_eval { remove_const(constant_name) if const_defined?(constant_name) }
26
+ end
27
+
28
+ remove_ivars(model)
29
+ model.instance_methods(false).each { |method| model.send(:undef_method, method) }
30
+
31
+ DataMapper::Model.descendants.delete(model)
32
+ end
33
+ end
34
+
35
+ def self.remove_ivars(object, instance_variables = object.instance_variables)
36
+ seen = {}
37
+ stack = instance_variables.map { |var| [ object, var ] }
38
+
39
+ while node = stack.pop
40
+ object, ivar = node
41
+
42
+ # skip "global" and non-DM objects
43
+ next if object.kind_of?(DataMapper::Logger) ||
44
+ object.kind_of?(DataMapper::Model::DescendantSet) ||
45
+ object.kind_of?(DataMapper::Adapters::AbstractAdapter) ||
46
+ object.class.name[0, 13] == 'DataObjects::'
47
+
48
+ # skip classes and modules in the DataMapper namespace
49
+ next if object.kind_of?(Module) &&
50
+ !object.name.nil? &&
51
+ object.name[0, 12] == 'DataMapper::'
52
+
53
+ # skip when the ivar is no longer defined in the object
54
+ next unless object.instance_variable_defined?(ivar)
55
+
56
+ value = object.instance_variable_get(ivar)
57
+ object.__send__(:remove_instance_variable, ivar) unless object.frozen?
58
+
59
+ # skip when the value was seen
60
+ next if seen.key?(value.object_id)
61
+ seen[value.object_id] = true
62
+
63
+ stack.concat value.instance_variables.map { |ivar| [ value, ivar ] }
64
+ end
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,165 @@
1
+ require 'dm-core'
2
+
3
+ module DataMapper
4
+ module Spec
5
+
6
+ class << self
7
+
8
+ def root
9
+ @root ||= default_root
10
+ end
11
+
12
+ def root=(path)
13
+ @root = Pathname(path)
14
+ end
15
+
16
+ %w[setup setup! adapter adapter_name].each do |action|
17
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
18
+ def #{action}(kind = :default)
19
+ perform_action(kind, :#{action})
20
+ end
21
+ RUBY
22
+ end
23
+
24
+ def configure
25
+ @configured = begin
26
+ setup_logger
27
+ require_plugins
28
+ require_spec_adapter
29
+ true
30
+ end
31
+ end
32
+
33
+ def configured?
34
+ @configured
35
+ end
36
+
37
+ def setup_logger
38
+ if log = ENV['LOG']
39
+ logger = DataMapper::Logger.new(log_stream(log), :debug)
40
+ logger.auto_flush = true
41
+ end
42
+ end
43
+
44
+ def require_spec_adapter
45
+ if ENV['ADAPTER'] == 'in_memory'
46
+ ENV['ADAPTER_SUPPORTS'] = 'all'
47
+ Adapters.use(Adapters::InMemoryAdapter)
48
+ else
49
+ require "dm-#{ENV['ADAPTER']}-adapter/spec/setup"
50
+ end
51
+ end
52
+
53
+ def require_plugins
54
+ plugins = ENV['PLUGINS'] || ENV['PLUGIN']
55
+ plugins = plugins.to_s.split(/[,\s]+/).push('dm-migrations').uniq
56
+ plugins.each { |plugin| require plugin }
57
+ end
58
+
59
+ def spec_adapters
60
+ @spec_adapters ||= {}
61
+ end
62
+
63
+ private
64
+
65
+ def perform_action(kind, action)
66
+ configure unless configured?
67
+ spec_adapters[kind].send(action)
68
+ end
69
+
70
+ def default_root
71
+ Pathname(Dir.pwd).join('spec')
72
+ end
73
+
74
+ def log_stream(log)
75
+ log == 'file' ? root.join('log/dm.log') : $stdout
76
+ end
77
+
78
+ end
79
+
80
+ module Adapters
81
+
82
+ def self.use(adapter_class)
83
+ Spec.spec_adapters[:default] = adapter_class.new(:default)
84
+ Spec.spec_adapters[:alternate] = adapter_class.new(:alternate)
85
+ end
86
+
87
+ class Adapter
88
+
89
+ attr_reader :name
90
+
91
+ def initialize(name)
92
+ @name = name.to_sym
93
+ end
94
+
95
+ def adapter
96
+ @adapter ||= setup!
97
+ end
98
+
99
+ alias :setup :adapter
100
+
101
+ def setup!
102
+ adapter = DataMapper.setup(name, connection_uri)
103
+ test_connection(adapter)
104
+ adapter
105
+ rescue Exception => e
106
+ puts "Could not connect to the database using '#{connection_uri}' because of: #{e.inspect}"
107
+ end
108
+
109
+ def adapter_name
110
+ @adapter_name ||= infer_adapter_name
111
+ end
112
+
113
+ def connection_uri
114
+ "#{adapter_name}://#{username}:#{password}@localhost/#{storage_name}"
115
+ end
116
+
117
+ def storage_name
118
+ send("#{name}_storage_name")
119
+ end
120
+
121
+ def default_storage_name
122
+ "datamapper_default_tests"
123
+ end
124
+
125
+ def alternate_storage_name
126
+ "datamapper_alternate_tests"
127
+ end
128
+
129
+ def username
130
+ 'datamapper'
131
+ end
132
+
133
+ def password
134
+ 'datamapper'
135
+ end
136
+
137
+ # Test the connection
138
+ #
139
+ # Overwrite this method if you need to perform custom connection testing
140
+ #
141
+ # @raise [Exception]
142
+ def test_connection(adapter)
143
+ if adapter.respond_to?(:select)
144
+ adapter.select('SELECT 1')
145
+ end
146
+ end
147
+
148
+ private
149
+
150
+ def infer_adapter_name
151
+ demodulized = ActiveSupport::Inflector.demodulize(self.class.name.chomp('Adapter'))
152
+ ActiveSupport::Inflector.underscore(demodulized).freeze
153
+ end
154
+
155
+ end
156
+
157
+ class InMemoryAdapter < Adapter
158
+ def connection_uri
159
+ { :adapter => :in_memory }
160
+ end
161
+ end
162
+
163
+ end
164
+ end
165
+ end
@@ -1,6 +1,17 @@
1
1
  share_examples_for 'An Adapter' do
2
2
 
3
3
  def self.adapter_supports?(*methods)
4
+
5
+ # FIXME obviously this needs a real fix!
6
+ # --------------------------------------
7
+ # Probably, delaying adapter_supports?
8
+ # to be executed after DataMapper.setup
9
+ # has been called will solve our current
10
+ # problem with described_type() being nil
11
+ # for as long as DataMapper.setup wasn't
12
+ # called
13
+ return true if ENV['ADAPTER_SUPPORTS'] == 'all'
14
+
4
15
  methods.all? do |method|
5
16
  # TODO: figure out a way to see if the instance method is only inherited
6
17
  # from the Abstract Adapter, and not defined in it's class. If that is
@@ -132,8 +143,8 @@ share_examples_for 'An Adapter' do
132
143
  if adapter_supports?(:read, :create)
133
144
  describe 'query matching' do
134
145
  before :all do
135
- @red = Heffalump.create(:color => 'red')
136
- @two = Heffalump.create(:num_spots => 2)
146
+ @red = Heffalump.create(:color => 'red')
147
+ @two = Heffalump.create(:num_spots => 2)
137
148
  @five = Heffalump.create(:num_spots => 5)
138
149
  end
139
150
 
@@ -182,10 +193,13 @@ share_examples_for 'An Adapter' do
182
193
  end
183
194
 
184
195
  it 'should be able to search for objects in an empty list and another OR condition (match none on the empty list)' do
185
- Heffalump.all(:conditions => DataMapper::Query::Conditions::Operation.new(
186
- :or,
187
- DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:color], []),
188
- DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:num_spots], [5]))).should == [ @five ]
196
+ Heffalump.all(
197
+ :conditions => DataMapper::Query::Conditions::Operation.new(
198
+ :or,
199
+ DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:color], []),
200
+ DataMapper::Query::Conditions::Comparison.new(:in, Heffalump.properties[:num_spots], [5])
201
+ )
202
+ ).should == [ @five ]
189
203
  end
190
204
 
191
205
  it 'should be able to search for objects not included in an array of values' do
@@ -225,7 +239,7 @@ share_examples_for 'An Adapter' do
225
239
 
226
240
  describe 'regexp' do
227
241
  before do
228
- if (defined?(DataMapper::Adapters::Sqlite3Adapter) && @adapter.kind_of?(DataMapper::Adapters::Sqlite3Adapter) ||
242
+ if (defined?(DataMapper::Adapters::SqliteAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqliteAdapter) ||
229
243
  defined?(DataMapper::Adapters::SqlserverAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqlserverAdapter))
230
244
  pending 'delegate regexp matches to same system that the InMemory and YAML adapters use'
231
245
  end
@@ -32,7 +32,7 @@ share_examples_for 'A public Resource' do
32
32
  end
33
33
 
34
34
  it 'should return true' do
35
- @return.should be_true
35
+ @return.should be(true)
36
36
  end
37
37
  end
38
38
 
@@ -43,7 +43,7 @@ share_examples_for 'A public Resource' do
43
43
  end
44
44
 
45
45
  it 'should return false' do
46
- @return.should be_false
46
+ @return.should be(false)
47
47
  end
48
48
  end
49
49
 
@@ -56,7 +56,7 @@ share_examples_for 'A public Resource' do
56
56
  end
57
57
 
58
58
  it 'should return true' do
59
- @return.should be_true
59
+ @return.should be(true)
60
60
  end
61
61
  end
62
62
 
@@ -69,7 +69,7 @@ share_examples_for 'A public Resource' do
69
69
  end
70
70
 
71
71
  it 'should return true' do
72
- @return.should be_true
72
+ @return.should be(true)
73
73
  end
74
74
  end
75
75
 
@@ -83,7 +83,7 @@ share_examples_for 'A public Resource' do
83
83
  end
84
84
 
85
85
  it 'should return false' do
86
- @return.should be_false
86
+ @return.should be(false)
87
87
  end
88
88
  end
89
89
 
@@ -96,7 +96,7 @@ share_examples_for 'A public Resource' do
96
96
  end
97
97
 
98
98
  it 'should return true' do
99
- @return.should be_true
99
+ @return.should be(true)
100
100
  end
101
101
  end
102
102
 
@@ -104,13 +104,13 @@ share_examples_for 'A public Resource' do
104
104
  describe 'when comparing to a resource with a different repository, but the same properties' do
105
105
  before :all do
106
106
  rescue_if @skip do
107
- @other = @alternate_repository.scope { @user_model.create(@user.attributes) }
107
+ @other = @repository.scope { @user_model.create(@user.attributes) }
108
108
  @return = @user.__send__(method, @other)
109
109
  end
110
110
  end
111
111
 
112
- it 'should return true' do
113
- @return.should be_true
112
+ it 'should return false' do
113
+ @return.should be(false)
114
114
  end
115
115
  end
116
116
  end
@@ -122,7 +122,7 @@ share_examples_for 'A public Resource' do
122
122
  describe '#<=>' do
123
123
  describe 'when the default order properties are equal with another resource' do
124
124
  before :all do
125
- rescue_if @skip do
125
+ rescue_if @skip && RUBY_VERSION < '1.9.2' do
126
126
  @other = @user_model.new(:name => 'dbussink')
127
127
  @return = @user <=> @other
128
128
  end
@@ -135,7 +135,7 @@ share_examples_for 'A public Resource' do
135
135
 
136
136
  describe 'when the default order property values are sorted before another resource' do
137
137
  before :all do
138
- rescue_if @skip do
138
+ rescue_if @skip && RUBY_VERSION < '1.9.2' do
139
139
  @other = @user_model.new(:name => 'c')
140
140
  @return = @user <=> @other
141
141
  end
@@ -148,7 +148,7 @@ share_examples_for 'A public Resource' do
148
148
 
149
149
  describe 'when the default order property values are sorted after another resource' do
150
150
  before :all do
151
- rescue_if @skip do
151
+ rescue_if @skip && RUBY_VERSION < '1.9.2' do
152
152
  @other = @user_model.new(:name => 'e')
153
153
  @return = @user <=> @other
154
154
  end
@@ -199,6 +199,19 @@ share_examples_for 'A public Resource' do
199
199
  end
200
200
  end
201
201
 
202
+ describe 'with a new resource with a property set' do
203
+ before :all do
204
+ rescue_if @skip do
205
+ @user = @user.model.new
206
+ @user.name = 'dbussink'
207
+ end
208
+ end
209
+
210
+ it 'should return the expected values' do
211
+ @user.attributes.should == {:name => 'dbussink'}
212
+ end
213
+ end
214
+
202
215
  describe 'with a saved resource' do
203
216
  it 'should return the expected values' do
204
217
  @user.attributes.only(:name, :description, :age).should == { :name => 'dbussink', :description => 'Test', :age => 25 }
@@ -242,7 +255,7 @@ share_examples_for 'A public Resource' do
242
255
  end
243
256
 
244
257
  it 'should successfully remove a resource' do
245
- @return.should be_true
258
+ @return.should be(true)
246
259
  end
247
260
 
248
261
  it 'should mark the destroyed resource as readonly' do
@@ -250,7 +263,7 @@ share_examples_for 'A public Resource' do
250
263
  end
251
264
 
252
265
  it "should return true when calling #{method} on a destroyed resource" do
253
- @resource.__send__(method).should be_true
266
+ @resource.__send__(method).should be(true)
254
267
  end
255
268
 
256
269
  it 'should remove resource from persistent storage' do
@@ -350,7 +363,7 @@ share_examples_for 'A public Resource' do
350
363
 
351
364
  it 'should not raise an exception' do
352
365
  lambda {
353
- @user.dirty?.should be_true
366
+ @user.dirty?.should be(true)
354
367
  }.should_not raise_error(SystemStackError)
355
368
  end
356
369
  end
@@ -364,7 +377,7 @@ share_examples_for 'A public Resource' do
364
377
 
365
378
  it 'should not raise an exception' do
366
379
  lambda {
367
- @user.dirty?.should be_true
380
+ @user.dirty?.should be(true)
368
381
  }.should_not raise_error(SystemStackError)
369
382
  end
370
383
  end
@@ -373,13 +386,13 @@ share_examples_for 'A public Resource' do
373
386
  before :all do
374
387
  rescue_if @skip do
375
388
  @user.children = [ @user.parent = @user_model.new(:name => 'Parent', :comment => @comment) ]
376
- @user.save.should be_true
389
+ @user.save.should be(true)
377
390
  end
378
391
  end
379
392
 
380
393
  it 'should not raise an exception' do
381
394
  lambda {
382
- @user.dirty?.should be_true
395
+ @user.dirty?.should be(true)
383
396
  }.should_not raise_error(SystemStackError)
384
397
  end
385
398
  end
@@ -395,7 +408,7 @@ share_examples_for 'A public Resource' do
395
408
  end
396
409
 
397
410
  it 'should return true' do
398
- @return.should be_true
411
+ @return.should be(true)
399
412
  end
400
413
  end
401
414
 
@@ -406,7 +419,7 @@ share_examples_for 'A public Resource' do
406
419
  end
407
420
 
408
421
  it 'should return false' do
409
- @return.should be_false
422
+ @return.should be(false)
410
423
  end
411
424
  end
412
425
 
@@ -419,7 +432,7 @@ share_examples_for 'A public Resource' do
419
432
  end
420
433
 
421
434
  it 'should return false' do
422
- @return.should be_false
435
+ @return.should be(false)
423
436
  end
424
437
  end
425
438
 
@@ -430,7 +443,7 @@ share_examples_for 'A public Resource' do
430
443
  end
431
444
 
432
445
  it 'should return false' do
433
- @return.should be_false
446
+ @return.should be(false)
434
447
  end
435
448
  end
436
449
 
@@ -443,7 +456,7 @@ share_examples_for 'A public Resource' do
443
456
  end
444
457
 
445
458
  it 'should return true' do
446
- @return.should be_true
459
+ @return.should be(true)
447
460
  end
448
461
  end
449
462
 
@@ -457,7 +470,7 @@ share_examples_for 'A public Resource' do
457
470
  end
458
471
 
459
472
  it 'should return false' do
460
- @return.should be_false
473
+ @return.should be(false)
461
474
  end
462
475
  end
463
476
 
@@ -470,7 +483,7 @@ share_examples_for 'A public Resource' do
470
483
  end
471
484
 
472
485
  it 'should return true' do
473
- @return.should be_true
486
+ @return.should be(true)
474
487
  end
475
488
  end
476
489
 
@@ -478,13 +491,13 @@ share_examples_for 'A public Resource' do
478
491
  describe 'when comparing to a resource with a different repository, but the same properties' do
479
492
  before :all do
480
493
  rescue_if @skip do
481
- @other = @alternate_repository.scope { @user_model.create(@user.attributes) }
494
+ @other = @repository.scope { @user_model.create(@user.attributes) }
482
495
  @return = @user.eql?(@other)
483
496
  end
484
497
  end
485
498
 
486
- it 'should return true' do
487
- @return.should be_true
499
+ it 'should return false' do
500
+ @return.should be(false)
488
501
  end
489
502
  end
490
503
  end
@@ -617,7 +630,7 @@ share_examples_for 'A public Resource' do
617
630
  describe 'on an anonymous resource' do
618
631
  before do
619
632
  rescue_if @skip do
620
- @user = @user.class.first(:fields => [ :description ])
633
+ @user = @user.model.first(:fields => [ :description ])
621
634
  @user.description.should == 'Test'
622
635
  end
623
636
  end
@@ -645,7 +658,7 @@ share_examples_for 'A public Resource' do
645
658
  end
646
659
 
647
660
  it 'should return false' do
648
- @user.readonly?.should be_false
661
+ @user.readonly?.should be(false)
649
662
  end
650
663
  end
651
664
 
@@ -657,19 +670,19 @@ share_examples_for 'A public Resource' do
657
670
  end
658
671
 
659
672
  it 'should return false' do
660
- @user.readonly?.should be_false
673
+ @user.readonly?.should be(false)
661
674
  end
662
675
  end
663
676
 
664
677
  describe 'on a destroyed resource' do
665
678
  before :all do
666
679
  rescue_if @skip do
667
- @user.destroy.should be_true
680
+ @user.destroy.should be(true)
668
681
  end
669
682
  end
670
683
 
671
684
  it 'should return true' do
672
- @user.readonly?.should be_true
685
+ @user.readonly?.should be(true)
673
686
  end
674
687
  end
675
688
 
@@ -682,7 +695,7 @@ share_examples_for 'A public Resource' do
682
695
  end
683
696
 
684
697
  it 'should return true' do
685
- @user.readonly?.should be_true
698
+ @user.readonly?.should be(true)
686
699
  end
687
700
  end
688
701
  end
@@ -691,6 +704,17 @@ share_examples_for 'A public Resource' do
691
704
  it { @user.should respond_to(method) }
692
705
 
693
706
  describe "##{method}" do
707
+ before :all do
708
+ @user_model.class_eval do
709
+ attr_accessor :save_hook_call_count
710
+
711
+ before :save do
712
+ @save_hook_call_count ||= 0
713
+ @save_hook_call_count += 1
714
+ end
715
+ end
716
+ end
717
+
694
718
  describe 'on a new, not dirty resource' do
695
719
  before :all do
696
720
  @user = @user_model.new
@@ -698,13 +722,27 @@ share_examples_for 'A public Resource' do
698
722
  end
699
723
 
700
724
  it 'should return false' do
701
- @return.should be_false
725
+ @return.should be(false)
726
+ end
727
+
728
+ it 'should call save hook expected number of times' do
729
+ @user.save_hook_call_count.should be_nil
702
730
  end
703
731
  end
704
732
 
705
733
  describe 'on a not new, not dirty resource' do
734
+ before :all do
735
+ rescue_if @skip do
736
+ @return = @user.__send__(method)
737
+ end
738
+ end
739
+
706
740
  it 'should return true even when resource is not dirty' do
707
- @user.__send__(method).should be_true
741
+ @return.should be(true)
742
+ end
743
+
744
+ it 'should call save hook expected number of times' do
745
+ @user.save_hook_call_count.should be_nil
708
746
  end
709
747
  end
710
748
 
@@ -717,12 +755,16 @@ share_examples_for 'A public Resource' do
717
755
  end
718
756
 
719
757
  it 'should save a resource succesfully when dirty' do
720
- @return.should be_true
758
+ @return.should be(true)
721
759
  end
722
760
 
723
761
  it 'should actually store the changes to persistent storage' do
724
762
  @user.attributes.should == @user.reload.attributes
725
763
  end
764
+
765
+ it 'should call save hook expected number of times' do
766
+ @user.save_hook_call_count.should == (method == :save ? 1 : nil)
767
+ end
726
768
  end
727
769
 
728
770
  describe 'on a dirty invalid resource' do
@@ -733,7 +775,11 @@ share_examples_for 'A public Resource' do
733
775
  end
734
776
 
735
777
  it 'should not save an invalid resource' do
736
- @user.__send__(method).should be_false
778
+ @user.__send__(method).should be(false)
779
+ end
780
+
781
+ it 'should call save hook expected number of times' do
782
+ @user.save_hook_call_count.should == (method == :save ? 1 : nil)
737
783
  end
738
784
  end
739
785
 
@@ -749,13 +795,13 @@ share_examples_for 'A public Resource' do
749
795
 
750
796
  it 'should save resource' do
751
797
  pending_if !@user.respond_to?(:comments) do
752
- @return.should be_true
798
+ @return.should be(true)
753
799
  end
754
800
  end
755
801
 
756
802
  it 'should save the first resource created through new' do
757
803
  pending_if !@user.respond_to?(:comments) do
758
- @first_comment.new?.should be_false
804
+ @first_comment.new?.should be(false)
759
805
  end
760
806
  end
761
807
 
@@ -767,7 +813,7 @@ share_examples_for 'A public Resource' do
767
813
 
768
814
  it 'should save the second resource created through the constructor' do
769
815
  pending "Changing a belongs_to parent should add the resource to the correct association" do
770
- @second_comment.new?.should be_false
816
+ @second_comment.new?.should be(false)
771
817
  end
772
818
  end
773
819
 
@@ -800,7 +846,7 @@ share_examples_for 'A public Resource' do
800
846
 
801
847
  it 'should return true' do
802
848
  pending_if !@user.respond_to?(:comments) do
803
- @return.should be_true
849
+ @return.should be(true)
804
850
  end
805
851
  end
806
852
 
@@ -829,7 +875,7 @@ share_examples_for 'A public Resource' do
829
875
 
830
876
  it 'should not raise an exception when saving the resource' do
831
877
  pending do
832
- lambda { @first_comment.send(method).should be_false }.should_not raise_error
878
+ lambda { @first_comment.send(method).should be(false) }.should_not raise_error
833
879
  end
834
880
  end
835
881
  end
@@ -847,7 +893,7 @@ share_examples_for 'A public Resource' do
847
893
  end
848
894
 
849
895
  it 'should succesfully save the resource' do
850
- @return.should be_true
896
+ @return.should be(true)
851
897
  end
852
898
 
853
899
  it 'should not have a dirty dependency' do
@@ -904,7 +950,7 @@ share_examples_for 'A public Resource' do
904
950
  end
905
951
 
906
952
  it 'should save a resource succesfully when dirty' do
907
- @return.should be_true
953
+ @return.should be(true)
908
954
  end
909
955
 
910
956
  it 'should actually store the changes to persistent storage' do
@@ -930,7 +976,7 @@ share_examples_for 'A public Resource' do
930
976
  end
931
977
 
932
978
  it 'should return true' do
933
- @response.should be_true
979
+ @response.should be(true)
934
980
  end
935
981
 
936
982
  it 'should save the child' do
@@ -946,21 +992,15 @@ share_examples_for 'A public Resource' do
946
992
  end
947
993
 
948
994
  it 'should relate the child to the parent' do
949
- pending_if @one_to_one_through do
950
- @child.model.get(*@child.key).referrer.should == @parent
951
- end
995
+ @child.model.get(*@child.key).referrer.should == @parent
952
996
  end
953
997
 
954
998
  it 'should relate the parent to the grandparent' do
955
- pending_if @one_to_one_through do
956
- @parent.model.get(*@parent.key).referrer.should == @grandparent
957
- end
999
+ @parent.model.get(*@parent.key).referrer.should == @grandparent
958
1000
  end
959
1001
 
960
1002
  it 'should relate the grandparent to nothing' do
961
- pending_if @one_to_one_through do
962
- @grandparent.model.get(*@grandparent.key).referrer.should be_nil
963
- end
1003
+ @grandparent.model.get(*@grandparent.key).referrer.should be_nil
964
1004
  end
965
1005
  end
966
1006
 
@@ -987,7 +1027,7 @@ share_examples_for 'A public Resource' do
987
1027
 
988
1028
  it 'should not raise an exception' do
989
1029
  lambda {
990
- @user.__send__(method).should be_true
1030
+ @user.__send__(method).should be(true)
991
1031
  }.should_not raise_error(SystemStackError)
992
1032
  end
993
1033
  end
@@ -1001,7 +1041,7 @@ share_examples_for 'A public Resource' do
1001
1041
 
1002
1042
  it 'should not raise an exception' do
1003
1043
  lambda {
1004
- @user.__send__(method).should be_true
1044
+ @user.__send__(method).should be(true)
1005
1045
  }.should_not raise_error(SystemStackError)
1006
1046
  end
1007
1047
  end
@@ -1015,7 +1055,7 @@ share_examples_for 'A public Resource' do
1015
1055
 
1016
1056
  it 'should not raise an exception' do
1017
1057
  lambda {
1018
- @user.__send__(method).should be_true
1058
+ @user.__send__(method).should be(true)
1019
1059
  }.should_not raise_error(SystemStackError)
1020
1060
  end
1021
1061
  end
@@ -1046,18 +1086,6 @@ share_examples_for 'A public Resource' do
1046
1086
  it { @user.should respond_to(method) }
1047
1087
 
1048
1088
  describe "##{method}" do
1049
- describe 'with no arguments' do
1050
- before :all do
1051
- rescue_if @skip do
1052
- @return = @user.__send__(method)
1053
- end
1054
- end
1055
-
1056
- it 'should return true' do
1057
- @return.should be_true
1058
- end
1059
- end
1060
-
1061
1089
  describe 'with attributes' do
1062
1090
  before :all do
1063
1091
  rescue_if @skip do
@@ -1067,7 +1095,7 @@ share_examples_for 'A public Resource' do
1067
1095
  end
1068
1096
 
1069
1097
  it 'should return true' do
1070
- @return.should be_true
1098
+ @return.should be(true)
1071
1099
  end
1072
1100
 
1073
1101
  it 'should update attributes of Resource' do
@@ -1082,29 +1110,23 @@ share_examples_for 'A public Resource' do
1082
1110
 
1083
1111
  describe 'with attributes where one is a parent association' do
1084
1112
  before :all do
1085
- rescue_if 'Use table aliases to avoid ambiguous named in query', @one_to_one_through do
1113
+ rescue_if @skip do
1086
1114
  @attributes = { :referrer => @user_model.create(:name => 'dkubb', :age => 33, :comment => @comment) }
1087
1115
  @return = @user.__send__(method, @attributes)
1088
1116
  end
1089
1117
  end
1090
1118
 
1091
1119
  it 'should return true' do
1092
- pending_if @one_to_one_through do
1093
- @return.should be_true
1094
- end
1120
+ @return.should be(true)
1095
1121
  end
1096
1122
 
1097
1123
  it 'should update attributes of Resource' do
1098
- pending_if @one_to_one_through do
1099
- @attributes.each { |key, value| @user.__send__(key).should == value }
1100
- end
1124
+ @attributes.each { |key, value| @user.__send__(key).should == value }
1101
1125
  end
1102
1126
 
1103
1127
  it 'should persist the changes' do
1104
- pending_if @one_to_one_through do
1105
- resource = @user_model.get(*@user.key)
1106
- @attributes.each { |key, value| resource.__send__(key).should == value }
1107
- end
1128
+ resource = @user_model.get(*@user.key)
1129
+ @attributes.each { |key, value| resource.__send__(key).should == value }
1108
1130
  end
1109
1131
  end
1110
1132
 
@@ -1116,7 +1138,7 @@ share_examples_for 'A public Resource' do
1116
1138
  end
1117
1139
 
1118
1140
  it 'should return false' do
1119
- @return.should be_false
1141
+ @return.should be(false)
1120
1142
  end
1121
1143
 
1122
1144
  it 'should not persist the changes' do
@@ -1124,6 +1146,21 @@ share_examples_for 'A public Resource' do
1124
1146
  end
1125
1147
  end
1126
1148
 
1149
+ describe 'on a new resource' do
1150
+ before :all do
1151
+ rescue_if @skip do
1152
+ @user = @user.model.new(@user.attributes)
1153
+ @user.age = 99
1154
+ end
1155
+ end
1156
+
1157
+ it 'should raise an exception' do
1158
+ lambda {
1159
+ @user.__send__(method, :admin => true)
1160
+ }.should raise_error(DataMapper::UpdateConflictError, "#{@user.model}##{method} cannot be called on a new resource")
1161
+ end
1162
+ end
1163
+
1127
1164
  describe 'on a dirty resource' do
1128
1165
  before :all do
1129
1166
  rescue_if @skip do