Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #3 from olivierlacan/patch-1
Converted README to markdown and added syntax highlighting
  • Loading branch information
mokolabs committed Jul 4, 2014
2 parents 3236d18 + e2914e2 commit 9c7457d
Show file tree
Hide file tree
Showing 2 changed files with 235 additions and 227 deletions.
235 changes: 235 additions & 0 deletions README.md
@@ -0,0 +1,235 @@
# Trucker
Trucker is a gem that helps migrate legacy data into a Rails app.

## Installation

### Install the trucker gem
`sudo gem install trucker`

### Add the gem
Add trucker to your <em>config.gem</em> block in `environment.rb`.
```ruby
config.gem "trucker"
```

### Generate the basic trucker files
```bash
script/generate truck
```

This will do the following things:
- Add legacy adapter to database.yml
- Add legacy base class
- Add legacy sub classes for all existing models
- Add app/models/legacy to autoload_paths in Rails Initializer config block
- Generate sample migration task (using pluralized model names)

### Update the legacy database adapter in <em>database.yml</em> with your legacy database info

```yaml
legacy:
adapter: mysql
encoding: utf8
database: app_legacy
username: root
password:
```

(By convention, we recommend naming your legacy database `APP_NAME_legacy`.)

### Database
If the legacy database doesn't already exist, add it.
```bash
rake db:create:all
```

### Legacy data
Import your legacy data into the legacy database.
```bash
mysql -u root app_legacy < old_database.sql
```

### `set_table_name`
Update `set_table_name` in each of your legacy models as needed.
```ruby
class LegacyPost < LegacyBase
set_table_name "LEGACY_TABLE_NAME_GOES_HERE"
end
```

### Field mappings
Update legacy model field mappings as needed.

```ruby
class LegacyPost < LegacyBase
set_table_name "YOUR LEGACY TABLE NAME GOES HERE"

def map
{
:headline => self.title.squish,
:body => self.long_text.squish
}
end
end
```

New model attributes on the left side.
Legacy model attributes on the right side.
(aka :new_field => legacy_field)

### Need to tweak some data?
Just add some core ruby methods or add a helper method.

```ruby
class LegacyPost < LegacyBase
set_table_name "YOUR LEGACY TABLE NAME GOES HERE"

def map
{
:headline => self.title.squish.capitalize, # <= Added capitalize method
:body => tweak_body(self.long_text.squish) # <= Added tweak_body method
}
end

# Insert helper methods as needed
def tweak_body(body)
body = body.gsub(/<br \//,"\n") # <= Convert break tags into normal line breaks
body = body.gsub(/teh/, "the") # <= Fix common typos
end
end
```

### Start migrating!
```bash
rake db:migrate:posts
```

## Migration command line options
Trucker supports a few command line options when migrating records:

```bash
rake db:migrate:posts limit=100 (migrates 100 records)
rake db:migrate:posts limit=100 offset=100 (migrates 100 records, but skip the first 100 records)
```

## Custom migration labels
You can tweak the default migration output generated by Trucker by using the `:label` option.

```bash
rake db:migrate:posts
=> Migrating posts

rake db:migrate:posts, :label => "blog posts"
=> Migrating blog posts
```

## Custom helpers
Trucker is intended for migrating data from fairly simple web apps that started life on PHP, Perl, etc. So, if you're migrating data from an enterprise system, this may not be your best choice.

That said, if you need to pull off a complex migration for a model, you can use a custom helper method to override Trucker's default migrate method in your rake task.

```ruby
namespace :db do
namespace :migrate do
...
desc 'Migrate pain_in_the_ass model'
task :pain_in_the_ass => :environment do
Trucker.migrate :pain_in_the_ass, :helper => pain_in_the_ass_migration
end
end
end

def pain_in_the_ass_migration
# Custom code goes here
end
```

Then just copy the migrate method from `lib/trucker.rb` and tweak accordingly.

As an example, here's a custom helper used to migrate join tables on a bunch of models.

```ruby
namespace :db do
namespace :migrate do

desc 'Migrates join tables'
task :joins => :environment do
migrate :joins, :helper => :migrate_joins
end

end
end

def migrate_joins
puts "Migrating #{number_of_records || "all"} joins #{"after #{offset_for_records}" if offset_for_records}"

["chain", "firm", "function", "style", "website"].each do |model|

# Start migration
puts "Migrating theaters_#{model.pluralize}"

# Delete existing joins
ActiveRecord::Base.connection.execute("TRUNCATE table theaters_#{model.pluralize}")

# Tweak model ids and foreign keys to match model syntax
if model == 'website'
model_id = "url_id"
send_foreign_key = "url_id".to_sym
else
model_id = "#{model}_id"
send_foreign_key = "#{model}_id".to_sym
end

# Create join object class
join = Object.const_set("Theaters#{model.classify}", Class.new(ActiveRecord::Base))

# Set model foreign key
model_foreign_key = "#{model}_id".to_sym

# Migrate join (unless duplicate)
"LegacyTheater#{model.classify}".constantize.find(:all, with(:order => model_id)).each do |record|

unless join.find(:first, :conditions => {:theater_id => record.theater_id, model_foreign_key => record.send(send_foreign_key)})
attributes = {
model_foreign_key => record.send(send_foreign_key),
:theater_id => record.theater_id
}

# Check if theater chain is current
attributes[:is_current] = {'Yes' => 1, 'No' => 0, '' => 0}[record.current] if model == 'chain'

# Migrate join
join.create(attributes)
end
end
end
end
```

## Sample application
Check out the [Trucker sample app](http://github.com/mokolabs/trucker_sample_app) for a working example of Trucker-based legacy data migration.


## Background
Trucker is based on a migration technique using legacy models first pioneered by Dave Thomas:
http://pragdave.blogs.pragprog.com/pragdave/2006/01/sharing_externa.html


## Note on patches/pull requests
- Fork the project.
- Make your feature addition or bug fix.
- Add tests for it. This is important so we don't break a future version unintentionally.
- Commit your changes, but do not mess with the rakefile, version, or history.
(if you want to have your own version, that is fine but bump version in a commit by itself so we can ignore when we pull)
- Send a pull request. Bonus points for topic branches.


## Contributors
- Patrick Crowley / mokolabs
- Rob Kaufman / notch8
- Jordan Fowler / TheBreeze
- Roel Bondoc / roelbondoc


## Copyright
Copyright (c) 2010 Patrick Crowley and Rob Kaufman. See [LICENSE](LICENSE) for details.

0 comments on commit 9c7457d

Please sign in to comment.