legacy_migrations 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --backtrace
@@ -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