legacy_migrations 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{legacy_migrations}
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bernie Telles"]
12
- s.date = %q{2010-03-15}
12
+ s.date = %q{2010-03-17}
13
13
  s.description = %q{Rails plugin for transferring or updating data between two db structures.}
14
14
  s.email = %q{bernardo.telles@dms.myflorida.com}
15
15
  s.extra_rdoc_files = [
@@ -31,8 +31,8 @@ Gem::Specification.new do |s|
31
31
  "lib/legacy_migrations/squirrel/extensions.rb",
32
32
  "lib/legacy_migrations/squirrel/paginator.rb",
33
33
  "lib/legacy_migrations/squirrel/squirrel.rb",
34
+ "lib/legacy_migrations/status_report.rb",
34
35
  "lib/legacy_migrations/transformations.rb",
35
- "lib/legacy_migrations/validation_helper.rb",
36
36
  "rails/init.rb",
37
37
  "spec/db/schema.rb",
38
38
  "spec/db/test.sqlite3",
@@ -0,0 +1,94 @@
1
+ module LegacyMigrations
2
+
3
+ #The StatusReport is returned from each transfer_from and update_from
4
+ #function. Its purpose is to keep track of all the operations
5
+ #you've done so far, and to help you log information about them
6
+ #after they are complete.
7
+ #
8
+ #Each status report has a many operations (one for each transfer or update)
9
+ #
10
+ #Each Operation has a source, destination, type (transfer or update),
11
+ #inserts (array of records inserted), updates (array of records updated),
12
+ #validation errors, sequence and source type.
13
+ #
14
+ class StatusReport
15
+ include Singleton
16
+ attr_reader :operations, :sequence
17
+
18
+ def add_operation(args)
19
+ @sequence ? @sequence += 1 : @sequence = 1
20
+ @operations ||= []
21
+ operation = Operation.new(args.merge({:sequence => @sequence}))
22
+ @operations << operation
23
+ operation
24
+ end
25
+
26
+ def operation_with(*args)
27
+ @operations ||= []
28
+ @operations.first do |operation|
29
+ result = true
30
+ args.each do |property, value|
31
+ result = false unless operation.send(property) == value
32
+ end
33
+ result
34
+ end[0]
35
+ end
36
+ end
37
+
38
+ class ValidationError
39
+ attr_accessor :source_record, :destination_record, :errors
40
+ def initialize(destination_record, source_record)
41
+ @source_record = source_record.dup
42
+ @destination_record = destination_record.dup
43
+ @errors = @destination_record.errors.dup
44
+ end
45
+ def pretty_output
46
+ puts "Validation error saving record. Invalid columns:"
47
+ @errors.each do |attr, error|
48
+ puts " #{attr} in the new record #{error}"
49
+ puts " Value of #{attr}: #{@destination_record.send(attr.to_sym)}"
50
+ end
51
+ puts " Source record: #{@source_record.inspect}"
52
+ end
53
+ end
54
+
55
+ class Operation
56
+ attr_accessor :source, :destination, :source_type,
57
+ :sequence, :inserts, :updates,
58
+ :validation_errors, :type
59
+
60
+ def initialize(properties)
61
+ properties.each do |property, value|
62
+ send("#{property.to_s}=", value) if respond_to? "#{property.to_s}="
63
+ end
64
+ end
65
+
66
+ def record_update(updated_record)
67
+ @updates ||= []
68
+ @updates << updated_record
69
+ end
70
+
71
+ def record_insert(new_record)
72
+ @inserts ||= []
73
+ @inserts << new_record
74
+
75
+ end
76
+
77
+ def add_validation_error(new_record, from_record)
78
+ @validation_errors ||= []
79
+ validation_error = ValidationError.new(new_record, from_record)
80
+ @validation_errors << validation_error
81
+ validation_error
82
+ end
83
+
84
+ def description
85
+ inserts = @inserts.try(:size) || 0
86
+ updates = @updates.try(:size) || 0
87
+ insert_phrase = "#{inserts} #{inserts == 1 ? 'insert' : 'inserts'}"
88
+ update_phrase = "#{updates} #{updates == 1 ? 'update' : 'updates'}"
89
+ actions = [insert_phrase, update_phrase].join(' and ') << '.'
90
+ "#{@type.capitalize} of data from #{@source.to_s.pluralize} to #{@destination.to_s.pluralize} resulted in #{actions}"
91
+ end
92
+ end
93
+
94
+ end
@@ -24,20 +24,29 @@ module LegacyMigrations
24
24
  def transfer_from(from_table, *args, &block)
25
25
 
26
26
  configure_transfer(from_table, *args) { yield }
27
+ @current_operation = StatusReport.instance.add_operation :source => @from_table,
28
+ :destination => @to_table,
29
+ :source_type => args.extract_options![:source_type] || :active_record,
30
+ :type => 'transfer'
31
+
27
32
 
28
33
  source_iterator(@limit, @type).each do |from_record|
29
34
  new_destination_record(from_record)
30
35
  end
36
+ @status_report
31
37
  end
32
38
 
33
39
  def update_from(from_table, *args, &block)
34
40
 
35
41
  configure_transfer(from_table, *args) { yield }
36
42
 
43
+ @current_operation = StatusReport.instance.add_operation :source => @from_table,
44
+ :destination => @to_table,
45
+ :source_type => args.extract_options![:source_type] || :active_record,
46
+ :type => 'update'
37
47
  source_iterator(@limit, @type).each do |from_record|
38
48
  matching_records = @conditions.call(from_record)
39
49
 
40
- #debugger if from_record.name == 'smithers'
41
50
  unless matching_records.empty?
42
51
  matching_records.each do |to_record|
43
52
  @columns.each do |to, from|
@@ -45,15 +54,17 @@ module LegacyMigrations
45
54
  end
46
55
 
47
56
  if @options[:validate]
48
- report_validation_errors(to_record, from_record)
57
+ report_validation_errors(to_record, from_record, 'update')
49
58
  else
50
59
  to_record.save(false)
60
+ @current_operation.record_update(to_record)
51
61
  end
52
62
  end
53
63
  else
54
64
  new_destination_record(from_record)
55
65
  end
56
66
  end
67
+ @status_report
57
68
  end
58
69
 
59
70
  private
@@ -65,6 +76,7 @@ module LegacyMigrations
65
76
 
66
77
  @from_table = from_table
67
78
  @to_table = @options[:to]
79
+ @status_report = StatusReport.instance
68
80
 
69
81
  yield
70
82
 
@@ -80,15 +92,23 @@ module LegacyMigrations
80
92
  new_record = @to_table.new(columns)
81
93
 
82
94
  if @options[:validate]
83
- report_validation_errors(new_record, from_record)
95
+ report_validation_errors(new_record, from_record, 'insert')
84
96
  else
85
97
  new_record.save(false)
98
+ @current_operation.record_insert(new_record)
86
99
  end
87
100
  end
101
+
102
+ def report_validation_errors(new_record, from_record, type = 'insert')
103
+ if new_record.save
104
+ @current_operation.send("record_#{type}", new_record)
105
+ else
106
+ puts @current_operation.add_validation_error(new_record, from_record).pretty_output
107
+ end
108
+ end
88
109
  end
89
110
  include LegacyMigrations
90
111
  include LegacyMigrations::Transformations
91
- include LegacyMigrations::ValidationHelper
92
112
  include LegacyMigrations::SourceIterators
93
113
  include LegacyMigrations::RowMatchers
94
114
 
@@ -66,6 +66,31 @@ describe LegacyMigrations do
66
66
  Animal.find_by_name('albert').should be_instance_of(Animal)
67
67
  Animal.find_by_first_name('albert').should be_instance_of(Animal)
68
68
  end
69
+ it "always returns a full status report" do
70
+ Person.create(:name => 'aoeu')
71
+ transfer_from Person, :to => Animal do
72
+ from :name, :to => :name
73
+ end
74
+ a = update_from Person, :to => Animal do
75
+ based_on do
76
+ name == from.name
77
+ end
78
+ from :name, :to => :name
79
+ end
80
+ a.operations.size == 2
81
+ a.operations[1].type == 'update'
82
+ end
83
+
84
+ it "records all changes by default" do
85
+ Person.create(:name => 'aoeu')
86
+ a = transfer_from Person, :to => Animal do
87
+ from :name, :to => :name
88
+ end
89
+ operation = a.operations.last
90
+ operation.inserts.size.should == 1
91
+ operation.inserts[0].should be_instance_of Animal
92
+ operation.description.should == "Transfer of data from People to Animals resulted in 1 insert and 0 updates."
93
+ end
69
94
  end
70
95
  describe 'update_from' do
71
96
  it "updates with simple column matching" do
@@ -36,7 +36,6 @@ describe "transformations" do
36
36
  end
37
37
  end
38
38
  Animal.first.first_name.should == 'MY FIRST NAME'
39
-
40
39
  end
41
40
  describe "match_same_name_attributes" do
42
41
  it "transfers same-name attributes" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legacy_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernie Telles
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-03-15 00:00:00 -04:00
12
+ date: 2010-03-17 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -46,8 +46,8 @@ files:
46
46
  - lib/legacy_migrations/squirrel/extensions.rb
47
47
  - lib/legacy_migrations/squirrel/paginator.rb
48
48
  - lib/legacy_migrations/squirrel/squirrel.rb
49
+ - lib/legacy_migrations/status_report.rb
49
50
  - lib/legacy_migrations/transformations.rb
50
- - lib/legacy_migrations/validation_helper.rb
51
51
  - rails/init.rb
52
52
  - spec/db/schema.rb
53
53
  - spec/db/test.sqlite3
@@ -1,14 +0,0 @@
1
- module LegacyMigrations
2
- module ValidationHelper
3
- def report_validation_errors(new_record, from_record)
4
- unless new_record.save
5
- puts "Validation error saving new record. Invalid columns:"
6
- new_record.errors.each do |attr, error|
7
- puts " #{attr} in the new record #{error}"
8
- puts " Value of #{attr}: #{new_record.send(attr.to_sym)}"
9
- end
10
- puts " Source record: #{from_record.inspect}"
11
- end
12
- end
13
- end
14
- end