legacy_migrations 0.1.0
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/.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
|