trucker 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/BACKGROUND.markdown +236 -0
- data/INSTALL.markdown +30 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +47 -0
- data/VERSION.yml +5 -0
- data/generators/truck/USAGE +1 -0
- data/generators/truck/lib/insert_commands.rb +76 -0
- data/generators/truck/templates/legacy_base.rb +11 -0
- data/generators/truck/templates/legacy_model.erb +11 -0
- data/generators/truck/templates/legacy_task.erb +23 -0
- data/generators/truck/truck_generator.rb +36 -0
- data/lib/trucker.rb +50 -0
- data/rails/init.rb +1 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/trucker_spec.rb +7 -0
- metadata +113 -0
data/BACKGROUND.markdown
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
Background
|
2
|
+
==========
|
3
|
+
|
4
|
+
Trucker is based on a migration technique using LegacyModels first pioneered by Dave Thomas.
|
5
|
+
|
6
|
+
Sharing External ActiveRecord Connections
|
7
|
+
http://pragdave.blogs.pragprog.com/pragdave/2006/01/sharing_externa.html
|
8
|
+
|
9
|
+
Using this, I've developed a set of helpers for migrating code.
|
10
|
+
|
11
|
+
- /app/models/legacy/
|
12
|
+
- /app/models/legacy/legacy_base.rb
|
13
|
+
- /app/models/legacy/legacy_model.rb
|
14
|
+
- /config/database.yml
|
15
|
+
- /config/environment.rb
|
16
|
+
- /lib/migration_helper.rb
|
17
|
+
- /lib/tasks/migrate.rake
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
/app/models/legacy/
|
22
|
+
===================
|
23
|
+
|
24
|
+
This folder will contain the base Legacy model, and all subclasses.
|
25
|
+
|
26
|
+
|
27
|
+
/app/models/legacy/legacy_base.rb
|
28
|
+
=================================
|
29
|
+
|
30
|
+
This is the base Legacy model which connects to the legacy database and handles the migration.
|
31
|
+
|
32
|
+
class LegacyBase < ActiveRecord::Base
|
33
|
+
self.abstract_class = true
|
34
|
+
establish_connection "legacy"
|
35
|
+
|
36
|
+
def migrate
|
37
|
+
new_record = self.class.to_s.gsub(/Legacy/,'::').constantize.new(map)
|
38
|
+
new_record[:id] = self.id
|
39
|
+
new_record.save
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
/app/models/legacy/legacy_model.rb
|
46
|
+
=================================
|
47
|
+
|
48
|
+
This is a sample Legacy subclass, which specifies the legacy model name and defines a map of old field names to new field names. All Legacy models are stored in /app/models/legacy to keep your main app model namespace unaffected.
|
49
|
+
|
50
|
+
class LegacyModel < LegacyBase
|
51
|
+
set_table_name "model"
|
52
|
+
|
53
|
+
def map
|
54
|
+
{
|
55
|
+
:make => self.car_company.squish,
|
56
|
+
:model => self.car_name.squish
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
/config/environment.rb
|
65
|
+
======================
|
66
|
+
|
67
|
+
We need to update the app environment so we can load the legacy models correctly.
|
68
|
+
|
69
|
+
Rails::Initializer.run do |config|
|
70
|
+
config.load_paths += %W( #{RAILS_ROOT}/app/models/legacy )
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
/config/database.yml
|
76
|
+
====================
|
77
|
+
|
78
|
+
We need to add a custom database adapter so that we can connect to our legacy database.
|
79
|
+
|
80
|
+
By convention, I've used APPNAME_legacy for my legacy databases, but you can easily customize this.
|
81
|
+
|
82
|
+
legacy:
|
83
|
+
adapter: mysql
|
84
|
+
database: APPNAME_legacy
|
85
|
+
username: root
|
86
|
+
password:
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
/app/models/legacy/legacy_base.rb
|
91
|
+
=================================
|
92
|
+
|
93
|
+
This model connects to our legacy database, and provides a migration method.
|
94
|
+
|
95
|
+
class LegacyBase < ActiveRecord::Base
|
96
|
+
self.abstract_class = true
|
97
|
+
establish_connection "legacy"
|
98
|
+
|
99
|
+
def migrate
|
100
|
+
new_record = self.class.to_s.gsub(/Legacy/,'::').constantize.new(map)
|
101
|
+
new_record[:id] = self.id
|
102
|
+
new_record.save
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
/lib/migration_helper.rb
|
110
|
+
========================
|
111
|
+
|
112
|
+
This helper is used by the rake task to manage the actual migration process.
|
113
|
+
|
114
|
+
def migrate(name, options={})
|
115
|
+
# Grab custom entity label if present
|
116
|
+
label = options.delete(:label) if options[:label]
|
117
|
+
|
118
|
+
unless options[:helper]
|
119
|
+
|
120
|
+
# Grab model to migrate
|
121
|
+
model = name.to_s.singularize.capitalize
|
122
|
+
|
123
|
+
# Wipe out existing records
|
124
|
+
model.constantize.delete_all
|
125
|
+
|
126
|
+
# Status message
|
127
|
+
status = "Migrating "
|
128
|
+
status += "#{number_of_records || "all"} #{label || name}"
|
129
|
+
status += " after #{offset_for_records}" if offset_for_records
|
130
|
+
|
131
|
+
# Set import counter
|
132
|
+
counter = 0
|
133
|
+
counter += offset_for_records if offset_for_records
|
134
|
+
total_records = "Legacy#{model}".constantize.find(:all).size
|
135
|
+
|
136
|
+
# Start import
|
137
|
+
"Legacy#{model}".constantize.find(:all, with(options)).each do |record|
|
138
|
+
counter += 1
|
139
|
+
puts status + " (#{counter}/#{total_records})"
|
140
|
+
record.migrate
|
141
|
+
end
|
142
|
+
else
|
143
|
+
eval options[:helper].to_s
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def with(options={})
|
148
|
+
{:limit => number_of_records, :offset => offset_for_records}.merge(options)
|
149
|
+
end
|
150
|
+
|
151
|
+
def number_of_records
|
152
|
+
nil || ENV['limit'].to_i if ENV['limit'].to_i > 0
|
153
|
+
end
|
154
|
+
|
155
|
+
def offset_for_records
|
156
|
+
nil || ENV['offset'].to_i if ENV['offset'].to_i > 0
|
157
|
+
end
|
158
|
+
|
159
|
+
Available options include offset and limit:
|
160
|
+
|
161
|
+
rake db:migrate:architects limit=1000
|
162
|
+
rake db:migrate:architects limit=1000 offset=2000
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
/lib/tasks/migrate.rake
|
167
|
+
========================
|
168
|
+
|
169
|
+
This is the basic rake task for migrating legacy data. With a sample model, just add a new migration task with the pluralized name of your existing model. For more complicated migrations, the migrate method supports a helper method which will override the default migration behavior and allow you to do a highly customized migration.
|
170
|
+
|
171
|
+
require 'migration_helper'
|
172
|
+
|
173
|
+
namespace :db do
|
174
|
+
namespace :migrate do
|
175
|
+
|
176
|
+
desc 'Migrates architects'
|
177
|
+
task :architects => :environment do
|
178
|
+
migrate :architects
|
179
|
+
end
|
180
|
+
|
181
|
+
desc 'Migrates theaters'
|
182
|
+
task :architects => :environment do
|
183
|
+
migrate :theaters, :helper => :migrate_theaters
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def migrate_theaters
|
190
|
+
|
191
|
+
# Delete all theaters if delete_all=true
|
192
|
+
Theater.delete_all if ENV['delete_all']
|
193
|
+
|
194
|
+
# Set default conditions
|
195
|
+
conditions = ["status_publish = 'Yes' AND location_address1 != '' AND location_address1 IS NOT NULL"]
|
196
|
+
|
197
|
+
# Set counters to monitor migration
|
198
|
+
success, failure, skipped = 0, 0, 0
|
199
|
+
|
200
|
+
# Count number of theaters
|
201
|
+
start = Theater.count
|
202
|
+
|
203
|
+
# Migrate theaters
|
204
|
+
puts "\nMigrating #{number_of_records || "all"} theaters #{"after #{offset_for_records}\n\n" if offset_for_records}"
|
205
|
+
LegacyTheater.find(:all, with(:conditions => conditions)).each_with_index do |record, i|
|
206
|
+
|
207
|
+
# Migrate theater
|
208
|
+
new_record = record.migrate
|
209
|
+
message = "#{new_record.name} (#{record.id})"
|
210
|
+
|
211
|
+
if Theater.exists?(record.id)
|
212
|
+
puts "#{i+1} SKIP #{message}\n\n"
|
213
|
+
skipped += 1
|
214
|
+
elsif new_record.save
|
215
|
+
puts "#{i+1} PASS #{message}\n\n"
|
216
|
+
success += 1
|
217
|
+
else
|
218
|
+
puts "#{i+1} FAIL #{message}\n#{new_record.inspect}\n\n"
|
219
|
+
failure += 1
|
220
|
+
end
|
221
|
+
|
222
|
+
# Archive old theater data
|
223
|
+
archive_old_theater_data(record)
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
# Count number of theaters
|
228
|
+
finish = Theater.count
|
229
|
+
|
230
|
+
# Batch stats
|
231
|
+
percentage = (failure.to_f / (skipped + success + failure).to_f).to_f * 100
|
232
|
+
puts "BATCH: #{number_of_records || "all"} theaters => #{success} passed, #{failure} failed (#{percentage.truncate}%), #{skipped} skipped (already imported)"
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
|
data/INSTALL.markdown
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
Here are some imaginary install instructions.
|
3
|
+
|
4
|
+
1. Install the trucker gem and add to your gem config block.
|
5
|
+
|
6
|
+
2. Generate the basic trucker files
|
7
|
+
|
8
|
+
script/generate truck
|
9
|
+
|
10
|
+
- Add legacy adapter to database.yml
|
11
|
+
- Add legacy base class
|
12
|
+
- (Optionally) Add legacy sub classes for all existing models
|
13
|
+
- Add app/models/legacy to load path in Rails Initializer config block
|
14
|
+
- Generate sample migration task (using pluralized model names)
|
15
|
+
|
16
|
+
3. Update database.yml with legacy database info
|
17
|
+
|
18
|
+
4. Run rake db:create:all to create the legacy database
|
19
|
+
|
20
|
+
5. Import your legacy database.
|
21
|
+
(Make sure the legacy adapter is using the correct name.)
|
22
|
+
|
23
|
+
6. Update legacy model table names as needed
|
24
|
+
|
25
|
+
7. Update legacy model field mappings as needed
|
26
|
+
|
27
|
+
8. Start migrating!
|
28
|
+
rake db:migrate:models
|
29
|
+
|
30
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Patrick Crowley and Rob Kaufman
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= Trucker
|
2
|
+
|
3
|
+
Trucker is a gem for migrating legacy data into a Rails app.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2010 Patrick Crowley and Rob Kaufman. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "trucker"
|
8
|
+
gem.summary = %Q{Bring your legacy along}
|
9
|
+
gem.description = %Q{Trucker is a gem for migrating legacy data into a Rails app}
|
10
|
+
gem.email = "patrick@mokolabs.com"
|
11
|
+
gem.homepage = "http://github.com/mokolabs/trucker"
|
12
|
+
gem.authors = ["Patrick Crowley and Rob Kaufman"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_development_dependency "yard", ">= 0"
|
15
|
+
gem.files = FileList["[A-Z]*", "{generators,lib,rails}/**/*"]
|
16
|
+
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'spec/rake/spectask'
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
|
30
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
31
|
+
spec.libs << 'lib' << 'spec'
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :spec => :check_dependencies
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'yard'
|
42
|
+
YARD::Rake::YardocTask.new
|
43
|
+
rescue LoadError
|
44
|
+
task :yardoc do
|
45
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
46
|
+
end
|
47
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
script/generate truck
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
|
2
|
+
|
3
|
+
Rails::Generator::Commands::Base.class_eval do
|
4
|
+
def file_contains?(relative_destination, line)
|
5
|
+
File.read(destination_path(relative_destination)).include?(line)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Rails::Generator::Commands::Create.class_eval do
|
10
|
+
def insert_before(file, line, stop='^(class|module) .+$')
|
11
|
+
logger.insert "#{line} into #{file}"
|
12
|
+
unless options[:pretend] || file_contains?(file, line)
|
13
|
+
gsub_file file, /^#{stop}/ do |match|
|
14
|
+
"#{line}\n#{match}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def insert_after(file, line, stop='^(class|module) .+$')
|
20
|
+
logger.insert "#{line} into #{file}"
|
21
|
+
@run = false
|
22
|
+
unless options[:pretend] || file_contains?(file, line)
|
23
|
+
gsub_file file, /#{stop}/ do |match|
|
24
|
+
@run = true
|
25
|
+
"#{match}\n #{line}"
|
26
|
+
end
|
27
|
+
raise "Append Key Not Found, was looking for #{stop}" unless @run
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def append(file, line)
|
32
|
+
logger.insert "added legacy adapter to end of database.yml"
|
33
|
+
unless options[:pretend] || file_contains?(file, line)
|
34
|
+
File.open(file, "a") do |file|
|
35
|
+
file.write("\n" + line)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
Rails::Generator::Commands::Destroy.class_eval do
|
43
|
+
def insert_before(file, line, stop='')
|
44
|
+
logger.remove "#{line} from #{file}"
|
45
|
+
unless options[:pretend]
|
46
|
+
gsub_file file, "\n #{line}", ''
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def insert_after(file, line, stop='')
|
51
|
+
logger.remove "#{line} from #{file}"
|
52
|
+
unless options[:pretend]
|
53
|
+
gsub_file file, "\n #{line}", ''
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def append(file, line)
|
58
|
+
logger.insert "added legacy adapter to end of database.yml"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
Rails::Generator::Commands::List.class_eval do
|
64
|
+
def insert_before(file, line, stop='')
|
65
|
+
logger.insert "#{line} into #{file}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def insert_after(file, line, stop='')
|
69
|
+
logger.insert "#{line} into #{file}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def append(file, line)
|
73
|
+
logger.insert "added legacy adapter to end of database.yml"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'trucker'
|
2
|
+
include Trucker
|
3
|
+
|
4
|
+
namespace :db do
|
5
|
+
namespace :migrate do
|
6
|
+
|
7
|
+
<%- unless legacy_models.size > 0 -%>
|
8
|
+
# desc 'Migrates products'
|
9
|
+
# task :products => :environment do
|
10
|
+
# migrate :products
|
11
|
+
# end
|
12
|
+
<%- end -%>
|
13
|
+
|
14
|
+
<%- legacy_models.each do |model_name| -%>
|
15
|
+
desc 'Migrates <%= model_name.pluralize.downcase %>'
|
16
|
+
task :<%= model_name.pluralize.downcase %> => :environment do
|
17
|
+
Trucker.migrate :<%= model_name.pluralize.downcase %>
|
18
|
+
end
|
19
|
+
|
20
|
+
<%- end -%>
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
|
2
|
+
|
3
|
+
class TruckGenerator < Rails::Generator::Base
|
4
|
+
|
5
|
+
def manifest
|
6
|
+
record do |m|
|
7
|
+
@legacy_models = Dir.glob(RAILS_ROOT + '/app/models/*.rb').collect { |model_path| File.basename(model_path).gsub('.rb', '') }
|
8
|
+
|
9
|
+
m.directory 'app/models/legacy'
|
10
|
+
m.file 'legacy_base.rb', 'app/models/legacy/legacy_base.rb'
|
11
|
+
|
12
|
+
@legacy_models.each do |model_name|
|
13
|
+
m.template 'legacy_model.erb', "app/models/legacy/legacy_#{model_name.downcase}.rb", :assigns => { :model_name => model_name }
|
14
|
+
end
|
15
|
+
|
16
|
+
m.directory 'lib/tasks'
|
17
|
+
m.template 'legacy_task.erb', 'lib/tasks/legacy.rake', :assigns => { :legacy_models => @legacy_models }
|
18
|
+
|
19
|
+
snippet = <<EOS
|
20
|
+
legacy:
|
21
|
+
adapter: mysql
|
22
|
+
database: #{RAILS_ROOT.split('/').last}_legacy
|
23
|
+
encoding: utf8
|
24
|
+
username:
|
25
|
+
password:
|
26
|
+
EOS
|
27
|
+
|
28
|
+
m.append "config/database.yml", snippet
|
29
|
+
|
30
|
+
snippet = 'config.load_paths += %W( #{RAILS_ROOT}/app/models/legacy )'
|
31
|
+
m.insert_after "config/environment.rb", snippet, '^Rails::Initializer\.run do.+$'
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/trucker.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Trucker
|
2
|
+
|
3
|
+
def self.migrate(name, options={})
|
4
|
+
# Grab custom entity label if present
|
5
|
+
label = options.delete(:label) if options[:label]
|
6
|
+
|
7
|
+
unless options[:helper]
|
8
|
+
|
9
|
+
# Grab model to migrate
|
10
|
+
model = name.to_s.singularize.capitalize
|
11
|
+
|
12
|
+
# Wipe out existing records
|
13
|
+
model.constantize.delete_all
|
14
|
+
|
15
|
+
# Status message
|
16
|
+
status = "Migrating "
|
17
|
+
status += "#{number_of_records || "all"} #{label || name}"
|
18
|
+
status += " after #{offset_for_records}" if offset_for_records
|
19
|
+
|
20
|
+
# Set import counter
|
21
|
+
counter = 0
|
22
|
+
counter += offset_for_records if offset_for_records
|
23
|
+
total_records = "Legacy#{model}".constantize.find(:all).size
|
24
|
+
|
25
|
+
# Start import
|
26
|
+
"Legacy#{model}".constantize.find(:all, with(options)).each do |record|
|
27
|
+
counter += 1
|
28
|
+
puts status + " (#{counter}/#{total_records})"
|
29
|
+
record.migrate
|
30
|
+
end
|
31
|
+
else
|
32
|
+
eval options[:helper].to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def self.with(options={})
|
39
|
+
{:limit => number_of_records, :offset => offset_for_records}.merge(options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.number_of_records
|
43
|
+
nil || ENV['limit'].to_i if ENV['limit'].to_i > 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.offset_for_records
|
47
|
+
nil || ENV['offset'].to_i if ENV['offset'].to_i > 0
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'trucker'
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trucker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Patrick Crowley and Rob Kaufman
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-15 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 9
|
34
|
+
version: 1.2.9
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: yard
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
description: Trucker is a gem for migrating legacy data into a Rails app
|
52
|
+
email: patrick@mokolabs.com
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files:
|
58
|
+
- LICENSE
|
59
|
+
- README.rdoc
|
60
|
+
files:
|
61
|
+
- BACKGROUND.markdown
|
62
|
+
- INSTALL.markdown
|
63
|
+
- LICENSE
|
64
|
+
- README.rdoc
|
65
|
+
- Rakefile
|
66
|
+
- VERSION.yml
|
67
|
+
- generators/truck/USAGE
|
68
|
+
- generators/truck/lib/insert_commands.rb
|
69
|
+
- generators/truck/templates/legacy_base.rb
|
70
|
+
- generators/truck/templates/legacy_model.erb
|
71
|
+
- generators/truck/templates/legacy_task.erb
|
72
|
+
- generators/truck/truck_generator.rb
|
73
|
+
- lib/trucker.rb
|
74
|
+
- rails/init.rb
|
75
|
+
- spec/spec_helper.rb
|
76
|
+
- spec/trucker_spec.rb
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: http://github.com/mokolabs/trucker
|
79
|
+
licenses: []
|
80
|
+
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options:
|
83
|
+
- --charset=UTF-8
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
requirements: []
|
105
|
+
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.3.7
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: Bring your legacy along
|
111
|
+
test_files:
|
112
|
+
- spec/spec_helper.rb
|
113
|
+
- spec/trucker_spec.rb
|