legacy_migrations 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/MIT-LICENSE +20 -0
- data/README +44 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/config/database.yml +5 -0
- data/install.rb +1 -0
- data/lib/legacy_migrations.rb +94 -0
- data/lib/legacy_migrations/row_matchers.rb +38 -0
- data/lib/legacy_migrations/source_iterators.rb +22 -0
- data/lib/legacy_migrations/squirrel.rb +17 -0
- data/lib/legacy_migrations/squirrel/extensions.rb +36 -0
- data/lib/legacy_migrations/squirrel/paginator.rb +83 -0
- data/lib/legacy_migrations/squirrel/squirrel.rb +532 -0
- data/lib/legacy_migrations/transformations.rb +76 -0
- data/lib/legacy_migrations/validation_helper.rb +14 -0
- data/spec/db/schema.rb +21 -0
- data/spec/db/test.sqlite3 +0 -0
- data/spec/legacy_migrations_spec.rb +80 -0
- data/spec/lib/transformations_spec.rb +59 -0
- data/spec/models.rb +14 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +30 -0
- data/uninstall.rb +1 -0
- metadata +91 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
module LegacyMigrations
|
2
|
+
module Transformations
|
3
|
+
|
4
|
+
# Move data from the _from\_attribute_ in the 'from' table to a
|
5
|
+
# column _:to_ in the 'to' table
|
6
|
+
#
|
7
|
+
# ==== Options
|
8
|
+
#
|
9
|
+
# * <tt>:to</tt> - (Required) Column in destination table to fill in with value in 'from'
|
10
|
+
# * <tt>:if</tt> - specify a function that takes one parameter (the source table's RECORD)
|
11
|
+
# and returns true or false. The assignment is only made if the function returns a
|
12
|
+
# non-false value.
|
13
|
+
# * <tt>&block</tt> - if passed a block, the block takes one parameter,
|
14
|
+
# which is the value of the attribute in the _from_ parameter, then inserts the result of
|
15
|
+
# the block into the destination attribute.
|
16
|
+
# parameter and inserts the result of the block in the provided 'to' column.
|
17
|
+
def from(from_attribute, *args)
|
18
|
+
options = args.extract_options!
|
19
|
+
|
20
|
+
if options[:if]
|
21
|
+
if_method = Proc.new {|record| send(options[:if], record)}
|
22
|
+
else
|
23
|
+
if_method = Proc.new {|record| true }
|
24
|
+
end
|
25
|
+
#anyone want to give this a try in another language? ;-)
|
26
|
+
custom_method = Proc.new {|record|
|
27
|
+
if if_method.call(record)
|
28
|
+
if block_given?
|
29
|
+
yield(record.send(:[], from_attribute.to_s))
|
30
|
+
else
|
31
|
+
record.send(:[], from_attribute.to_s)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
}
|
38
|
+
|
39
|
+
@columns.merge!({options[:to] => custom_method})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Shortcut for transferring data between similar tables.
|
43
|
+
# For example, if two tables have a column named 'name', then using
|
44
|
+
# this function will transfer data from source table's 'name' column
|
45
|
+
# to the destination table's 'name' column.
|
46
|
+
#
|
47
|
+
# ==== Options
|
48
|
+
#
|
49
|
+
# * <tt>:only</tt> - Array of columns that you want to transfer, and
|
50
|
+
# that have the same name on both tables.
|
51
|
+
# * <tt>:except</tt> - Array of columns that you DON'T want to transfer,
|
52
|
+
# but that have the same name on both tables.
|
53
|
+
def match_same_name_attributes(*options)
|
54
|
+
|
55
|
+
options = options.extract_options!
|
56
|
+
same_name_attributes = @from_table.columns.map(&:name) & @to_table.columns.map(&:name)
|
57
|
+
|
58
|
+
if same_name_attributes
|
59
|
+
same_name_attributes = columns_from_options(same_name_attributes, options)
|
60
|
+
same_name_attributes.each do |same_name_attribute|
|
61
|
+
from same_name_attribute, :to => same_name_attribute
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def columns_from_options(columns, options)
|
69
|
+
columns.map!(&:to_sym)
|
70
|
+
columns = columns.select {|a| options[:only].include?(a)} if options[:only]
|
71
|
+
columns = columns.reject {|a| !options[:except].include?(a)} if options[:except]
|
72
|
+
columns
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,14 @@
|
|
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
|
data/spec/db/schema.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
|
3
|
+
create_table :people, :force => true do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :not_name
|
6
|
+
t.integer :age
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :animals, :force => true do |t|
|
10
|
+
t.string :name
|
11
|
+
t.string :not_name
|
12
|
+
t.integer :age
|
13
|
+
t.string :first_name
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :sex, :force => true do |t|
|
17
|
+
t.string :name
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
Binary file
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper.rb'))
|
2
|
+
|
3
|
+
describe LegacyMigrations do
|
4
|
+
require 'ruby-debug'
|
5
|
+
describe 'transfer_from' do
|
6
|
+
it "accepts a limit to the number of transfers to conduct" do
|
7
|
+
3.times {|a| Person.create(:name => 'my first name') }
|
8
|
+
|
9
|
+
transfer_from Person, :to => Animal, :limit => 2 do
|
10
|
+
match_same_name_attributes
|
11
|
+
end
|
12
|
+
Animal.all.count.should == 2
|
13
|
+
end
|
14
|
+
it "validates by default" do
|
15
|
+
Person.create(:name => 'aoeu 9')
|
16
|
+
transfer_from Person, :to => Animal do
|
17
|
+
match_same_name_attributes
|
18
|
+
end
|
19
|
+
Animal.all.count.should == 0
|
20
|
+
end
|
21
|
+
it "bypasses validation when the option is set" do
|
22
|
+
Person.create(:name => 'aoeu 9')
|
23
|
+
transfer_from Person, :to => Animal, :validate => false do
|
24
|
+
match_same_name_attributes
|
25
|
+
end
|
26
|
+
Animal.all.count.should == 1
|
27
|
+
end
|
28
|
+
it "accepts a CSV file" do
|
29
|
+
person = "a simple name,age\nalbert,123"
|
30
|
+
person_csv = FasterCSV.parse(person, :headers => :first_row)
|
31
|
+
transfer_from person_csv, :to => Animal, :source_type => :csv do
|
32
|
+
from 'a simple name', :to => :name
|
33
|
+
end
|
34
|
+
Animal.first.name.should == 'albert'
|
35
|
+
end
|
36
|
+
it "limits a CSV file" do
|
37
|
+
person = "a simple name,age\nalbert,123\nsmith,54"
|
38
|
+
person_csv = FasterCSV.parse(person, :headers => :first_row)
|
39
|
+
transfer_from person_csv, :to => Animal, :source_type => :csv, :limit => 1 do
|
40
|
+
from 'a simple name', :to => :name
|
41
|
+
end
|
42
|
+
Animal.all.count.should == 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
describe 'update_from' do
|
46
|
+
it "updates with simple column matching" do
|
47
|
+
Person.create(:name => 'smithers', :age => 4)
|
48
|
+
Animal.create(:name => 'smithers')
|
49
|
+
update_from Person, :to => Animal do
|
50
|
+
|
51
|
+
based_on do
|
52
|
+
name == from.name
|
53
|
+
end
|
54
|
+
|
55
|
+
from :name, :to => :name
|
56
|
+
from :age, :to => :age
|
57
|
+
end
|
58
|
+
Animal.find_by_name('smithers').age.should == 4
|
59
|
+
Animal.all.count.should == 1
|
60
|
+
end
|
61
|
+
it "inserts if a matching record does not exist" do
|
62
|
+
Person.create(:name => 'smithers', :age => 4)
|
63
|
+
Person.create(:name => 'simpson', :age => 8)
|
64
|
+
Animal.create(:name => 'simpson')
|
65
|
+
update_from Person, :to => Animal do
|
66
|
+
|
67
|
+
based_on do
|
68
|
+
name == from.name
|
69
|
+
end
|
70
|
+
|
71
|
+
from :name, :to => :name
|
72
|
+
from :age, :to => :age
|
73
|
+
end
|
74
|
+
Animal.find_by_name('smithers').age.should == 4
|
75
|
+
Animal.find_by_name('simpson').age.should == 8
|
76
|
+
Animal.all.count.should == 2
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper.rb'))
|
2
|
+
|
3
|
+
describe "transformations" do
|
4
|
+
describe 'from' do
|
5
|
+
it "transfers attributes, given the two names" do
|
6
|
+
Person.create(:name => 'my first name')
|
7
|
+
transfer_from Person, :to => Animal do
|
8
|
+
from :name, :to => :first_name
|
9
|
+
end
|
10
|
+
Animal.first.first_name.should == 'my first name'
|
11
|
+
end
|
12
|
+
it "transfers attributes, given a block" do
|
13
|
+
Person.create(:name => 'my first name')
|
14
|
+
transfer_from Person, :to => Animal do
|
15
|
+
from :name, :to => :first_name do |name|
|
16
|
+
name.upcase
|
17
|
+
end
|
18
|
+
end
|
19
|
+
Animal.first.first_name.should == 'MY FIRST NAME'
|
20
|
+
end
|
21
|
+
it 'allows user to specify an :if function' do
|
22
|
+
def function_returning_false(from_record); false; end
|
23
|
+
Person.create(:name => 'my first name')
|
24
|
+
transfer_from Person, :to => Animal do
|
25
|
+
from :name, :to => :first_name, :if => :function_returning_false
|
26
|
+
from :name, :to => :name
|
27
|
+
end
|
28
|
+
Animal.first.first_name.should == nil
|
29
|
+
Animal.first.name.should == 'my first name'
|
30
|
+
end
|
31
|
+
describe "match_same_name_attributes" do
|
32
|
+
it "transfers same-name attributes" do
|
33
|
+
Person.create(:name => 'same name')
|
34
|
+
transfer_from Person, :to => Animal do
|
35
|
+
match_same_name_attributes
|
36
|
+
end
|
37
|
+
Animal.first.name.should == 'same name'
|
38
|
+
end
|
39
|
+
it "lets the user select all attributes EXCEPT a few for transfer" do
|
40
|
+
Person.create(:name => 'choose_me', :not_name => 'not_this_one')
|
41
|
+
transfer_from Person, :to => Animal do
|
42
|
+
match_same_name_attributes :except => [:name]
|
43
|
+
end
|
44
|
+
animal = Animal.first
|
45
|
+
animal.name.should == 'choose_me'
|
46
|
+
animal.not_name.should == nil
|
47
|
+
end
|
48
|
+
it "lets the user select only some attributes for transfer" do
|
49
|
+
Person.create(:name => 'only', :not_name => 'not_this')
|
50
|
+
transfer_from Person, :to => Animal do
|
51
|
+
match_same_name_attributes :only => [:name]
|
52
|
+
end
|
53
|
+
animal = Animal.first
|
54
|
+
animal.name.should == 'only'
|
55
|
+
animal.not_name.should == nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/models.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class Person < ActiveRecord::Base
|
2
|
+
#name
|
3
|
+
#not_name
|
4
|
+
#age
|
5
|
+
end
|
6
|
+
|
7
|
+
class Animal < ActiveRecord::Base
|
8
|
+
validates_format_of :name, :with => /^(\D)*$/, :allow_nil => true
|
9
|
+
#name
|
10
|
+
#not_name
|
11
|
+
#first_name
|
12
|
+
#age
|
13
|
+
end
|
14
|
+
require 'legacy_migrations'
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#if Rails::VERSION::STRING =~ /^3\..*/
|
2
|
+
# require 'rspec'
|
3
|
+
# require 'rspec-rails'
|
4
|
+
# require 'ruby-debug'
|
5
|
+
#end
|
6
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','..','spec','spec_helper'))
|
7
|
+
$TESTING=true
|
8
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
|
+
|
10
|
+
|
11
|
+
plugin_spec_dir = File.dirname(__FILE__)
|
12
|
+
|
13
|
+
load(File.join(plugin_spec_dir, "db", "schema.rb"))
|
14
|
+
require 'fastercsv'
|
15
|
+
require 'models'
|
16
|
+
|
17
|
+
# == Fixtures
|
18
|
+
#
|
19
|
+
if Rails::VERSION::STRING =~ /^3\..*/
|
20
|
+
Rspec.configure do |config|
|
21
|
+
end
|
22
|
+
else
|
23
|
+
Spec::Runner.configure do |config|
|
24
|
+
|
25
|
+
config.use_transactional_fixtures = true
|
26
|
+
config.use_instantiated_fixtures = false
|
27
|
+
config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: legacy_migrations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bernie Telles
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-12 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
description: Rails plugin for transferring or updating data between two db structures.
|
26
|
+
email: bernardo.telles@dms.myflorida.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- MIT-LICENSE
|
36
|
+
- Rakefile
|
37
|
+
- VERSION
|
38
|
+
- config/database.yml
|
39
|
+
- install.rb
|
40
|
+
- lib/legacy_migrations.rb
|
41
|
+
- lib/legacy_migrations/row_matchers.rb
|
42
|
+
- lib/legacy_migrations/source_iterators.rb
|
43
|
+
- lib/legacy_migrations/squirrel.rb
|
44
|
+
- lib/legacy_migrations/squirrel/extensions.rb
|
45
|
+
- lib/legacy_migrations/squirrel/paginator.rb
|
46
|
+
- lib/legacy_migrations/squirrel/squirrel.rb
|
47
|
+
- lib/legacy_migrations/transformations.rb
|
48
|
+
- lib/legacy_migrations/validation_helper.rb
|
49
|
+
- spec/db/schema.rb
|
50
|
+
- spec/db/test.sqlite3
|
51
|
+
- spec/legacy_migrations_spec.rb
|
52
|
+
- spec/lib/transformations_spec.rb
|
53
|
+
- spec/models.rb
|
54
|
+
- spec/spec.opts
|
55
|
+
- spec/spec_helper.rb
|
56
|
+
- uninstall.rb
|
57
|
+
- README
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/btelles/legacy_migrations
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
requirements: []
|
80
|
+
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.3.5
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Rails plugin for transferring or updating data between two db structures.
|
86
|
+
test_files:
|
87
|
+
- spec/legacy_migrations_spec.rb
|
88
|
+
- spec/lib/transformations_spec.rb
|
89
|
+
- spec/models.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
- spec/db/schema.rb
|