caruby-core 1.4.7 → 1.4.9

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 (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