legacy_migrations 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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