caruby-core 1.4.7 → 1.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/History.txt +11 -0
  2. data/README.md +1 -1
  3. data/lib/caruby/cli/command.rb +27 -3
  4. data/lib/caruby/csv/csv_mapper.rb +2 -0
  5. data/lib/caruby/csv/csvio.rb +187 -169
  6. data/lib/caruby/database.rb +33 -16
  7. data/lib/caruby/database/lazy_loader.rb +23 -23
  8. data/lib/caruby/database/persistable.rb +32 -18
  9. data/lib/caruby/database/persistence_service.rb +20 -7
  10. data/lib/caruby/database/reader.rb +22 -21
  11. data/lib/caruby/database/search_template_builder.rb +7 -9
  12. data/lib/caruby/database/sql_executor.rb +52 -27
  13. data/lib/caruby/database/store_template_builder.rb +18 -13
  14. data/lib/caruby/database/writer.rb +107 -44
  15. data/lib/caruby/domain/attribute_metadata.rb +35 -25
  16. data/lib/caruby/domain/java_attribute_metadata.rb +43 -20
  17. data/lib/caruby/domain/merge.rb +9 -5
  18. data/lib/caruby/domain/reference_visitor.rb +4 -3
  19. data/lib/caruby/domain/resource_attributes.rb +52 -12
  20. data/lib/caruby/domain/resource_dependency.rb +129 -42
  21. data/lib/caruby/domain/resource_introspection.rb +1 -1
  22. data/lib/caruby/domain/resource_inverse.rb +20 -3
  23. data/lib/caruby/domain/resource_metadata.rb +20 -4
  24. data/lib/caruby/domain/resource_module.rb +190 -124
  25. data/lib/caruby/import/java.rb +39 -19
  26. data/lib/caruby/migration/migratable.rb +31 -6
  27. data/lib/caruby/migration/migrator.rb +126 -40
  28. data/lib/caruby/migration/uniquify.rb +0 -1
  29. data/lib/caruby/resource.rb +28 -5
  30. data/lib/caruby/util/attribute_path.rb +0 -2
  31. data/lib/caruby/util/class.rb +8 -5
  32. data/lib/caruby/util/collection.rb +5 -3
  33. data/lib/caruby/util/domain_extent.rb +0 -3
  34. data/lib/caruby/util/options.rb +10 -9
  35. data/lib/caruby/util/person.rb +41 -12
  36. data/lib/caruby/util/pretty_print.rb +1 -1
  37. data/lib/caruby/util/validation.rb +0 -28
  38. data/lib/caruby/version.rb +1 -1
  39. data/test/lib/caruby/import/java_test.rb +26 -9
  40. data/test/lib/caruby/migration/test_case.rb +103 -0
  41. data/test/lib/caruby/test_case.rb +231 -0
  42. data/test/lib/caruby/util/class_test.rb +2 -2
  43. data/test/lib/caruby/util/visitor_test.rb +3 -2
  44. data/test/lib/examples/galena/clinical_trials/migration/participant_test.rb +28 -0
  45. data/test/lib/examples/galena/clinical_trials/migration/test_case.rb +40 -0
  46. metadata +195 -170
  47. data/lib/caruby/domain/attribute_initializer.rb +0 -16
  48. data/test/lib/caruby/util/validation_test.rb +0 -14
@@ -1,4 +1,3 @@
1
- require 'caruby/migration/migratable'
2
1
  require 'caruby/domain/uniquify'
3
2
 
4
3
  module CaRuby
@@ -17,7 +17,7 @@ module CaRuby
17
17
  # This module defines essential common domain methods that enable the jRuby-Java API bridge.
18
18
  # Classes which include Domain must implement the +metadata+ Domain::Metadata accessor method.
19
19
  module Resource
20
- include Mergeable, Migratable, Persistable, Inversible, Validation
20
+ include Mergeable, Migratable, Persistable, Inversible
21
21
 
22
22
  # JRuby alert - Bug #5090 - JRuby 1.5 object_id no longer reserved, results in String value.
23
23
  # See http://jira.codehaus.org/browse/JRUBY-5090.
@@ -25,6 +25,7 @@ module CaRuby
25
25
  #
26
26
  # @return [Integer] the object id
27
27
  def proxy_object_id
28
+ # make a hash code on demand
28
29
  @_hc ||= (Object.new.object_id * 31) + 17
29
30
  end
30
31
 
@@ -54,8 +55,13 @@ module CaRuby
54
55
  end
55
56
  self
56
57
  end
58
+
59
+ # Sets the default attribute values for this auto-generated domain object.
60
+ def add_defaults_autogenerated
61
+ add_defaults_recursive
62
+ end
57
63
 
58
- # Validates this domain object and its #{ResourceAttributes.unproxied_cascaded_attributes}
64
+ # Validates this domain object and its #{ResourceAttributes.unproxied_save_template_attributes}
59
65
  # for completeness prior to a database create operation.
60
66
  # An object without an identifer is valid if it contains a non-nil value for each mandatory property.
61
67
  # Objects which have an identifier or have already been validated are skipped.
@@ -69,7 +75,7 @@ module CaRuby
69
75
  validate_local
70
76
  @validated = true
71
77
  end
72
- self.class.unproxied_cascaded_attributes.each do |attr|
78
+ self.class.unproxied_save_template_attributes.each do |attr|
73
79
  send(attr).enumerate { |dep| dep.validate }
74
80
  end
75
81
  self
@@ -167,6 +173,12 @@ module CaRuby
167
173
  def owner
168
174
  self.class.owner_attributes.detect_value { |attr| send(attr) }
169
175
  end
176
+
177
+ # @return [Symbol, nil] the attribute for which there is an owner reference,
178
+ # or nil if this domain object does not reference an owner
179
+ def effective_owner_attribute
180
+ self.class.owner_attributes.detect { |attr| send(attr) }
181
+ end
170
182
 
171
183
  # Sets this dependent's owner attribute to the given domain object.
172
184
  #
@@ -430,7 +442,7 @@ module CaRuby
430
442
  # @yieldparam [Resource] owner the domain object to print
431
443
  # @return [String] the domain object content
432
444
  def dump(&selector)
433
- database.lazy_loader.disable { DetailPrinter.new(self, &selector).pp_s }
445
+ do_without_lazy_loader { DetailPrinter.new(self, &selector).pp_s }
434
446
  end
435
447
 
436
448
  # Prints this domain object in the format:
@@ -708,7 +720,18 @@ module CaRuby
708
720
  attr_md = self.class.attribute_metadata(attribute)
709
721
  attr_md.property_descriptor.property_type if JavaAttributeMetadata === attr_md
710
722
  end
711
-
723
+
724
+ # Executes the given block with the database lazy loader disabled, if any.
725
+ #
726
+ # @yield the block to execute
727
+ def do_without_lazy_loader(&block)
728
+ if database then
729
+ database.lazy_loader.disable(&block)
730
+ else
731
+ yield
732
+ end
733
+ end
734
+
712
735
  # Returns the source => target hash of matches for the given attr_md newval sources and
713
736
  # oldval targets. If the matcher block is given, then that block is called on the sources
714
737
  # and targets. Otherwise, {Resource.match_all} is called.
@@ -2,8 +2,6 @@ require 'caruby/util/validation'
2
2
 
3
3
  # An AttributePath encapsulates an array of attributes that can be evaluated on a source object.
4
4
  class AttributePath < Array
5
- include Validation
6
-
7
5
  # Creates an AttributePath from the path Array, String or Symbol. A path string is a period-delimited sequence
8
6
  # of attributes, e.g. +person.name+.
9
7
  def initialize(path)
@@ -13,21 +13,21 @@ class Class
13
13
  alias :succ :superclass
14
14
 
15
15
  private
16
-
16
+
17
17
  # Creates an alias for each accessor method of the given attribute.
18
18
  #
19
19
  # @example
20
20
  # class Person
21
21
  # attr_reader :social_security_number
22
22
  # attr_accessor :postal_code
23
- # define_attribute_alias(:ssn, :social_security_number)
24
- # define_attribute_alias(:zip_code, :postal_code)
23
+ # alias_attribute(:ssn, :social_security_number)
24
+ # alias_attribute(:zip_code, :postal_code)
25
25
  # end
26
26
  # Person.method_defined?(:ssn) #=> true
27
27
  # Person.method_defined?(:ssn=) #=> false
28
28
  # Person.method_defined?(:zip_code) #=> true
29
29
  # Person.method_defined?(:zip_code=) #=> true
30
- def define_attribute_alias(aliaz, attribute)
30
+ def alias_attribute(aliaz, attribute)
31
31
  alias_method(aliaz, attribute) if method_defined?(attribute)
32
32
  writer = "#{attribute}=".to_sym
33
33
  alias_method("#{aliaz}=".to_sym, writer) if method_defined?(writer)
@@ -117,7 +117,10 @@ class Class
117
117
  # The block creates a proc which implements the new method body.
118
118
  #
119
119
  # @example
120
- # redefine_method(:ssn) { |old_method| lambda { send(old_method).delete('-').to_i } }
120
+ # redefine_method(:ssn) { |omth| lambda { send(omth).delete('-').to_i } }
121
+ # @param [Symbol] method the method to redefine
122
+ # @yield [old_method] the redefinition Proc
123
+ # @yieldparam old_method [Symbol] the method being redefined
121
124
  # @return [Symbol] an alias to the old method implementation
122
125
  def redefine_method(method)
123
126
  # make a new alias id method__base for the existing method.
@@ -1,7 +1,6 @@
1
1
  require 'set'
2
2
  require 'delegate'
3
3
  require 'enumerator'
4
- require 'generator'
5
4
  require 'caruby/util/class'
6
5
  require 'caruby/util/validation'
7
6
  require 'caruby/util/options'
@@ -229,10 +228,12 @@ module Enumerable
229
228
  # @yield [item] the transformer on the enumerated items
230
229
  # @yieldparam item an enumerated item
231
230
  # @return [Enumerable] an enumeration on the transformed values
232
- def wrap(&mapper)
231
+ def transform(&mapper)
233
232
  Transformer.new(self, &mapper)
234
233
  end
235
234
 
235
+ alias :wrap :transform
236
+
236
237
  def join(other)
237
238
  Joiner.new(self, other)
238
239
  end
@@ -276,7 +277,7 @@ module Enumerable
276
277
  # @param item the item to add
277
278
  # @return [Filter] self
278
279
  def <<(item)
279
- @base << value
280
+ @base << item
280
281
  self
281
282
  end
282
283
 
@@ -794,6 +795,7 @@ module Hashable
794
795
  include Hashable
795
796
 
796
797
  def initialize(*hashes)
798
+ if hashes.include?(nil) then raise ArgumentError.new("MultiHash is missing a component hash.") end
797
799
  @hashes = hashes
798
800
  end
799
801
 
@@ -7,8 +7,6 @@ require 'caruby/util/validation'
7
7
  # @example
8
8
  # DomainExtent.new { |klass, key| key.to_s + klass.name }.get(String, 'a') #=> aString
9
9
  class DomainExtent < LazyHash
10
- include Validation
11
-
12
10
  # Creates a new DomainExtent. The block passed to the constructor
13
11
  # is a factory to create an object on demand, with arguments
14
12
  # the target class and the target key. The default block is empty.
@@ -24,7 +22,6 @@ class DomainExtent < LazyHash
24
22
  # The factory accepts a single argument, the instance key, e.g.
25
23
  # set_factory(MyClass) { |key| MyClass.new(key) }
26
24
  def set_factory(klass, &factory)
27
- validate_type(klass => Class)
28
25
  # the current instances, if any
29
26
  instances = fetch(klass) if has_key?(klass)
30
27
  # make the key => instance class extent map
@@ -30,15 +30,16 @@ class Options
30
30
  def self.get(option, options, default=nil, &block)
31
31
  return default(default, &block) if options.nil?
32
32
  case options
33
- when Hash then
34
- value = options[option]
35
- value.nil? ? default(default, &block) : value
36
- when Enumerable then
37
- options.include?(option) ? true : default(default, &block)
38
- when Symbol then
39
- option == options ? true : default(default, &block)
40
- else
41
- raise ArgumentError.new("Options argument type is not supported; expected Hash or Symbol, found: #{options.class}")
33
+ when Hash then
34
+ value = options[option]
35
+ if String === value then value.strip! end
36
+ value.nil_or_empty? ? default(default, &block) : value
37
+ when Enumerable then
38
+ options.include?(option) ? true : default(default, &block)
39
+ when Symbol then
40
+ option == options ? true : default(default, &block)
41
+ else
42
+ raise ArgumentError.new("Options argument type is not supported; expected Hash or Symbol, found: #{options.class}")
42
43
  end
43
44
  end
44
45
 
@@ -4,12 +4,29 @@ require 'caruby/util/validation'
4
4
  module CaRuby
5
5
  module Person
6
6
  class Name
7
- include Validation
8
-
9
- attr_accessor :salutation, :qualifier, :credentials
10
- attr_reader :first, :last, :middle
7
+ # @return [String] the salutation, e.g. 'Mr.'
8
+ attr_accessor :salutation
9
+
10
+ # @return [String] the trailing name qualifier, e.g. 'III'
11
+ attr_accessor :qualifier
12
+
13
+ # @return [String] the trailing name credentials, e.g. 'MD'
14
+ attr_accessor :credentials
15
+
16
+ # @return [String] the first name
17
+ attr_reader :first
18
+
19
+ # @return [String] the middle name
20
+ attr_reader :middle
21
+
22
+ # @return [String] the ;ast name
23
+ attr_reader :last
11
24
 
12
25
  # Creates a new Name with the required last and optional first and middle components.
26
+ #
27
+ # @param [String] last the required last name
28
+ # @param [String, nil] first the optional first name
29
+ # @param [String, nil] middle the optional middle name
13
30
  def initialize(last, first=nil, middle=nil)
14
31
  # replace empty with nil
15
32
  @first = first unless first == ''
@@ -17,7 +34,8 @@ module CaRuby
17
34
  @middle = middle unless middle == ''
18
35
  end
19
36
 
20
- # Returns this Name as an array consisting of the first, middle and last fields.
37
+ # @return [(String, String, String)] this Name as an array consisting of the first,
38
+ # middle and last fields
21
39
  #
22
40
  # @example
23
41
  # Person.parse("Abe Lincoln").to_a #=> ["Abe", nil, "Lincoln"]
@@ -25,14 +43,14 @@ module CaRuby
25
43
  [@first, @middle, @last]
26
44
  end
27
45
 
28
- # Returns this Name in the format [Salutation] First [Middle] Last[, Credentials].
46
+ # @return [String] this Name in the format [Salutation] First [Middle] Last[, Credentials]
29
47
  def to_s
30
48
  name_s = [salutation, first, middle, last, qualifier].reject { |part| part.nil? }.join(' ')
31
49
  name_s << ', ' << credentials if credentials
32
50
  name_s
33
51
  end
34
52
 
35
- # Returns whether this Person's first, middle and last name components equal the other Person's.
53
+ # @return [Boolean] whether this Person's first, middle and last name components equal the other Person's
36
54
  def ==(other)
37
55
  self.class == other.class and first == other.first and middle == other.middle and last == other.last
38
56
  end
@@ -44,12 +62,15 @@ module CaRuby
44
62
  # * [salutation] [first [middle]] last [qualifier] [, credentials]
45
63
  # where _salutation_ ends in a period.
46
64
  #
47
- # Examples:
65
+ # Example input:
48
66
  # * Longfellow, Henry Wadsworth
49
67
  # * Longfellow, Henry Gallifant Wadsworth
50
68
  # * Henry Longfellow
51
69
  # * Longfellow
52
70
  # * Mr. Henry Wadsworth Longfellow III, MD, Ph.D.
71
+ #
72
+ # @param [String] name_s the name to parse
73
+ # @return [Name] the parsed Name
53
74
  def self.parse(name_s)
54
75
  return if name_s.blank?
55
76
  # the name component variables
@@ -94,8 +115,8 @@ module CaRuby
94
115
  name
95
116
  end
96
117
 
97
- # Raises ValidationError if there is neither a first nor a last name
98
- # or if there is a middle name but no first name.
118
+ # @raise [ValidationError] if there is neither a first nor a last name
119
+ # or if there is a middle name but no first name
99
120
  def validate
100
121
  if last.nil? and first.nil? then
101
122
  raise ValidationError.new("Name is missing both the first and last fields")
@@ -105,12 +126,20 @@ module CaRuby
105
126
  end
106
127
  end
107
128
 
108
- # Returns whether s ends in a period.
129
+ # @param [String] s a name fragment
130
+ # @return [Boolean] whether the fragment ends in a period
109
131
  def self.salutation?(s)
110
132
  s =~ /\.$/
111
133
  end
112
134
 
113
- # Returns whether s is Jr., Sr., II, III, etc.
135
+ # Returns whether the given name fragment is a recognized qualifier. The following
136
+ # qualifiers are recognized:
137
+ # * +Jr+ with optional period
138
+ # * +Sr+ with optional period
139
+ # * +I+, +II+ or +III+
140
+ #
141
+ # @param [String] s a name fragment
142
+ # @return [Boolean] whether s is a recognized qualifier
114
143
  def self.qualifier?(s)
115
144
  s and (s =~ /[J|S]r[.]?/ or s =~ /\AI+\Z/)
116
145
  end
@@ -124,7 +124,7 @@ module Enumerable
124
124
  # Pretty-prints the content within brackets, as is done by the Array pretty printer.
125
125
  def pretty_print(q)
126
126
  q.group(1, '[', ']') {
127
- q.seplist(self) {|v|
127
+ q.seplist(self) { |v|
128
128
  q.pp v
129
129
  }
130
130
  }
@@ -18,31 +18,3 @@ class Object
18
18
  nil? or (respond_to?(:empty?) and empty?)
19
19
  end
20
20
  end
21
-
22
- module Validation
23
- # A Validator is a procedure which responds to the +validate(value)+ method.
24
- class Validator < Proc
25
- alias :validate :call
26
- end
27
-
28
- # Validates that each key value in the value_type_assns value => type hash is an instance of the associated class.
29
- #
30
- # Raises ValidationError if the value is missing.
31
- # Raises TypeError if the value is not the specified type.
32
- def validate_type(value_type_assns)
33
- TYPE_VALIDATOR.validate(value_type_assns)
34
- end
35
-
36
- private
37
-
38
- def self.create_type_validator
39
- Validator.new do |value_type_assns|
40
- value_type_assns.each do |value, type|
41
- raise ArgumentError.new("Missing #{type.name} argument") if value.nil?
42
- raise TypeError.new("Unsupported argument type; expected: #{type.name} found: #{value.class.name}") unless type === value
43
- end
44
- end
45
- end
46
-
47
- TYPE_VALIDATOR = create_type_validator
48
- end
@@ -1,3 +1,3 @@
1
1
  module CaRuby
2
- VERSION = "1.4.7"
2
+ VERSION = "1.4.9"
3
3
  end
@@ -6,18 +6,26 @@ require 'caruby'
6
6
 
7
7
  class JavaTest < Test::Unit::TestCase
8
8
  def test_ruby_to_java_date_conversion
9
- ruby_date = DateTime.now
10
- java_date = Java::JavaUtil::Date.from_ruby_date(ruby_date)
11
- actual = java_date.to_ruby_date
12
- assert(CaRuby::Resource.value_equal?(ruby_date, actual), 'Ruby->Java->Ruby date conversion not idempotent')
9
+ rdt = DateTime.now
10
+ jdt = Java::JavaUtil::Date.from_ruby_date(rdt)
11
+ assert(CaRuby::Resource.value_equal?(rdt, jdt.to_ruby_date), 'Ruby->Java->Ruby date conversion not idempotent')
13
12
  end
14
13
 
15
14
  def test_java_to_ruby_date_conversion
16
- java_date = Java::JavaUtil::Calendar.instance.time
17
- ruby_date = java_date.to_ruby_date
18
- actual = Java::JavaUtil::Date.from_ruby_date(ruby_date)
19
- assert_equal(java_date.to_s, actual.to_s, 'Java->Ruby->Java date conversion not idempotent')
20
- assert_equal(java_date.to_ruby_date, ruby_date, 'Java->Ruby date reconversion not equal')
15
+ cal = Java::JavaUtil::Calendar.instance
16
+ verify_java_to_ruby_date_conversion(cal.time)
17
+ # roll back to a a different DST setting
18
+ if cal.timeZone.useDaylightTime then
19
+ verify_java_to_ruby_date_conversion(flip_DST(cal))
20
+ end
21
+ end
22
+
23
+ def flip_DST(cal)
24
+ isdt = cal.timeZone.inDaylightTime(cal.time)
25
+ 11.times do
26
+ cal.roll(Java::JavaUtil::Calendar::MONTH, false)
27
+ return cal.time if cal.timeZone.inDaylightTime(cal.time) != isdt
28
+ end
21
29
  end
22
30
 
23
31
  def test_to_ruby
@@ -55,4 +63,13 @@ class JavaTest < Test::Unit::TestCase
55
63
  assert(set.include?(2), "HashSet merge not updated")
56
64
  assert_same(set, set.clear, "HashSet clear result incorrect")
57
65
  end
66
+
67
+ private
68
+
69
+ def verify_java_to_ruby_date_conversion(jdate)
70
+ rdt = jdate.to_ruby_date
71
+ actual = Java::JavaUtil::Date.from_ruby_date(rdt)
72
+ assert_equal(jdate.to_s, actual.to_s, 'Java->Ruby->Java date conversion not idempotent')
73
+ assert_equal(jdate.to_ruby_date, rdt, 'Java->Ruby date reconversion not equal')
74
+ end
58
75
  end
@@ -0,0 +1,103 @@
1
+ LOG_FILE = 'test/results/log/migration.log'
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'test_case')
4
+ require 'caruby/domain/uniquify'
5
+ require 'caruby/migration/migrator'
6
+
7
+ module CaRuby
8
+ module MigrationTestCase
9
+ include CaRuby::TestCase
10
+
11
+ #@param [String] fixtures the fixtures directory
12
+ def setup(fixtures, database=nil)
13
+ super(database)
14
+ @fixtures = fixtures
15
+ # Clear the uniquifier for this migration.
16
+ CaRuby::ResourceUniquifier.instance.clear
17
+ end
18
+
19
+ ## MIGRATION TEST UTILITY METHODS ##
20
+
21
+ private
22
+
23
+ # Runs a migrator on the given input fixture and options.
24
+ #
25
+ # @param (see #create_migrator)
26
+ # @option (see #create_migrator)
27
+ def migrate_to_database(fixture, opts={}, &verifier)
28
+ mgtr = create_migrator(fixture, opts)
29
+ logger.debug { "Migration test migrating #{fixture} fixture..." }
30
+ mgtr.migrate_to_database(&verifier)
31
+ logger.debug { "Migration test migrated #{fixture} fixture." }
32
+ end
33
+
34
+ # Creates a new Migrator for the given fixture with the given options.
35
+ # If a factory block is provided, then that factory is called to make a new
36
+ # Migrator instance. Otherwise, {CaTissue::Migrator#initialize} makes the instance.
37
+ #
38
+ # If there is no :input option, then the migration input is set to the
39
+ # _fixture_.+csv+ file in the {#initialize} fixtures directory.
40
+ #
41
+ # @param [Symbol] fixture the migration test fixture
42
+ # @param [{Symbol => Object}] opts (see CaTissue::Migrator#initialize)
43
+ # @option (see CaTissue::Migrator#initialize)
44
+ # @return [CaTissue::Migrator]
45
+ # @yield [opts] the optional Migrator factory
46
+ def create_migrator(fixture, opts={}, &factory)
47
+ opts[:quiet] = true
48
+ opts[:input] ||= File.join(@fixtures, fixture.to_s + '.csv')
49
+ block_given? ? yield(opts) : CaRuby::Migrator.new(opts)
50
+ end
51
+
52
+ # Verifies that the given test fixture is successfully migrated.
53
+ # Each migrated target object is validated using {CaTissue::TestCase#verify_saved}.
54
+ # In addition, if a verifier block is given to this method, then that block is
55
+ # called on the target migration object, or nil if no target was migrated.
56
+ # Supported options are described in {CaTissue::Migrator#migrate}.
57
+ #
58
+ # @param (see #verify_target)
59
+ # @option (see #verify_target)
60
+ # @yield (see #verify_target)
61
+ # @yieldparam (see #verify_target)
62
+ def verify_save(fixture, opts={})
63
+ logger.debug { "Migrating the #{fixture} test fixture..." }
64
+ opts[:unique] = true unless opts.has_key?(:unique)
65
+ migrate_to_database(fixture, opts) do |tgt|
66
+ verify_saved(tgt)
67
+ yield tgt if block_given?
68
+ end
69
+ end
70
+
71
+ # Verifies the given fixture migration.
72
+ # Each migrated target object is validated using {#validate_target}.
73
+ # The target is migrated but not stored.
74
+ #
75
+ # @param [Symbol] fixture the test fixture to verify
76
+ # @param [<Symbol>] opts the migration options
77
+ # @option (see CaTissue::Migrator#migrate)
78
+ # @yield [target] verifies the given target
79
+ # @yieldparam [Resource] target the domain object to verify
80
+ def verify_target(fixture, opts={}, &verifier)
81
+ opts[:unique] ||= false
82
+ create_migrator(fixture, opts).migrate { |tgt| validate_target(tgt, &verifier) }
83
+ end
84
+
85
+ # Validates that the given target was successfully migrated.
86
+ # If a target was migrated, then this method calls {CaTissue::TestCase#verify_defaults}
87
+ # to confirm that the target can be stored.
88
+ # In addition, if a block is given to this method then the block is called on the
89
+ # (possibly nil) migration target.
90
+ #
91
+ # @param [Resource] target the domain object to verify
92
+ # @yield (see #verify_target)
93
+ # @yieldparam (see #verify_target)
94
+ def validate_target(target)
95
+ assert_not_nil(target, "Missing target")
96
+ logger.debug { "Validating migration target #{target}..." }
97
+ verify_defaults(target) if target
98
+ yield target if block_given?
99
+ logger.debug { "Validated migration target #{target}." }
100
+ target
101
+ end
102
+ end
103
+ end