data_migrate 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,25 +3,90 @@ Data Migrate
3
3
 
4
4
  Run data migrations alongside schema migrations.
5
5
 
6
- Data migrations are stored in db/data. They act like schema migrations, except they should be reserved for data migrations. For instance, if you realize you need to titleize all yours titles, this is the place to do it.
7
-
8
- Data migrations can be created at the same time as schema migrations, or independently. Database (db:) tasks have been added and extended to run on data migrations only, or in conjunction with the schema migration. For instance, `rake db:migrate:with_data` will run both schema and data migrations in the proper order.
6
+ Data migrations are stored in db/data. They act like schema
7
+ migrations, except they should be reserved for data migrations. For
8
+ instance, if you realize you need to titleize all yours titles, this
9
+ is the place to do it.
10
+
11
+ Why should I use this?
12
+ ----------------------
13
+
14
+ Its seems when a project hits a certain size, I get to manipulate data
15
+ outside the application itself. Changing defaults, new validations,
16
+ one-to-one to one-to-many... I found it a pain and dodgy to have to
17
+ step up migrations one by one, run a ruby script of some sort, then
18
+ resume migrations. It tanks a lot of the automation of deploy.
19
+
20
+ If you don't use the one off scripts, you could do it as a regular
21
+ migration. It'd be much better to keep concerns separate. The benefit
22
+ of having them separate has to do with your data model.
23
+
24
+ For instance, lets take an absurd example, to illustrate: You have
25
+ your infamous [Rails blog](http://media.rubyonrails.org/video/rails-0-5.mov)
26
+ that has posts with many comments. After some use, you decide you are
27
+ going to be a trend setter, and want only one comment per post, and
28
+ just the text. "Frist!" rules the day. Given that you:
29
+ - write a migration to add a comment column to Post
30
+ - write a migration to move the contents of the first comments to the Post
31
+ - drop the column_id column from Post
32
+ - drop the Comment model
33
+ - fix all your test/controller/view mojo.
34
+
35
+ You've just got bit. When you rake setup:development, the mess gets
36
+ mad at you after it creates your database, and starts cranking through
37
+ migrations. It gets to the part where you iterate over the comments
38
+ and it blows up. You don't have a comment model anymore for it to
39
+ even try and get 'all' from. You think you are smarter, and wrap the
40
+ AR call in a conditional based on the environment. That's fine until
41
+ you get that QA gal, and she wants her own thing. Then the UI people
42
+ get tired of waiting for the full stack to load on page refreshes, so
43
+ you have to edit past migrations...
44
+
45
+ With Data Migrate, you have the control. You can generate your
46
+ migrations as schema or data as you would as your work flow. For
47
+ setting tasks that don't require any intermediate AR activity, like
48
+ dev and test, you stick with db:migrate. For your prod, and qa, you
49
+ change their scripts to `db:migrate:with_data`. Of course you want to
50
+ test your migration, so you have the choice of `db:migrate:with_data` or
51
+ `data:migrate` to just capture that data change.
52
+
53
+ What's it do?
54
+ -------------
55
+
56
+ Data migrations are stored in db/data. They act like schema
57
+ migrations, except they should be reserved for data migrations. For
58
+ instance, if you realize you need to titleize all yours titles, this
59
+ is the place to do it. Running any of the provided rake tasks also
60
+ creates a data schema table to mirror the usual schema migrations
61
+ table to track all the goodness.
62
+
63
+ Data migrations can be created at the same time as schema migrations,
64
+ or independently. Database (db:) tasks have been added and extended
65
+ to run on data migrations only, or in conjunction with the schema
66
+ migration. For instance, `rake db:migrate:with_data` will run both
67
+ schema and data migrations in the proper order.
9
68
 
10
69
  Note: If a data and schema migration share the same version number, schema gets precedence when migrating up. Data does down.
11
70
 
12
71
  Rails 3 and Ruby 1.9
13
72
  --------------------
14
73
 
15
- Data Migrate is Rails 3.0.0 - 3.0.7, and Ruby 1.9 compatible
74
+ Data Migrate is Rails 3.0.0 - 3.0.7, and Ruby 1.9 compatible
16
75
 
17
76
  Installation
18
77
  ------------
19
- After adding Data Migrate to your project,
78
+ Add the gem to your project
79
+
80
+ # Gemfile
81
+ gem 'data_migrate'
20
82
 
21
- rails g data_migrate:install
22
- rake db:migrate
83
+ Then `bundle install` and you are ready to go.
23
84
 
24
- A table 'data_migrations' table will be generated.
85
+ So you know, when you use one of the provide rake tasks, a table
86
+ called 'data_migrations' will be created in your database. This
87
+ is to mirror the way the standard 'db' rake tasks work. If you've
88
+ installed previous to v1.1.0, you'll want to delete the
89
+ 'create\_data\_migrations_table' migration.
25
90
 
26
91
  Usage
27
92
  -----
@@ -76,3 +141,8 @@ Running `rake db:migrate:up:with_data VERSION=20110419021211` would execute the
76
141
  Going down instead of up would be the opposite.
77
142
 
78
143
  `rake db:migrate:status:with_data` provides and additional column to indicate which type of migration.
144
+
145
+ Thanks
146
+ ------
147
+ [Jeremy Durham](http://jeremydurham.com/) for fleshing out the idea with me, and providing guidance.
148
+ You! Yes, you. Thanks for checking it out.
@@ -1,3 +1,3 @@
1
1
  module DataMigrate
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,13 +1,6 @@
1
- require 'rails/generators/base'
2
1
  require 'rails/generators/named_base'
3
2
  module DataMigrate
4
3
  module Generators
5
- class InstallGenerator < Rails::Generators::Base #:nodoc:
6
- def self.source_root
7
- @_data_migrate_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'data_migrate', generator_name, 'templates'))
8
- end
9
- end
10
-
11
4
  class DataMigrationGenerator < Rails::Generators::NamedBase #:nodoc:
12
5
  def self.source_root
13
6
  @_data_migrate_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), generator_name, 'templates'))
@@ -9,7 +9,7 @@ module DataMigrate
9
9
  include Rails::Generators::Migration
10
10
 
11
11
  argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
12
- class_option :skip_schema_migration, :desc => 'Dont generate database migration file.', :type => :boolean
12
+ class_option :skip_schema_migration, :desc => 'Dont generate database schema migration file.', :type => :boolean
13
13
 
14
14
  def create_data_migration
15
15
  set_local_assigns!
@@ -2,8 +2,7 @@ namespace :db do
2
2
  namespace :migrate do
3
3
  desc "Migrate the database data and schema (options: VERSION=x, VERBOSE=false)."
4
4
  task :with_data => :environment do
5
- config = connect_to_database
6
- next unless config
5
+ assure_data_schema_table
7
6
 
8
7
  ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
9
8
  target_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
@@ -60,6 +59,7 @@ namespace :db do
60
59
  namespace :redo do
61
60
  desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
62
61
  task :with_data => :environment do
62
+ assure_data_schema_table
63
63
  if ENV["VERSION"]
64
64
  Rake::Task["db:migrate:down:with_data"].invoke
65
65
  Rake::Task["db:migrate:up:with_data"].invoke
@@ -75,7 +75,7 @@ namespace :db do
75
75
  task :with_data => :environment do
76
76
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
77
77
  raise "VERSION is required" unless version
78
- config = connect_to_database
78
+ assure_data_schema_table
79
79
  run_both = ENV["BOTH"] == "true"
80
80
  migrations = pending_migrations.keep_if{|m| m[:version] == version}
81
81
 
@@ -100,7 +100,7 @@ namespace :db do
100
100
  task :with_data => :environment do
101
101
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
102
102
  raise "VERSION is required" unless version
103
- config = connect_to_database
103
+ assure_data_schema_table
104
104
  run_both = ENV["BOTH"] == "true"
105
105
  migrations = past_migrations.keep_if{|m| m[:version] == version}
106
106
 
@@ -170,8 +170,7 @@ namespace :db do
170
170
  desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
171
171
  task :with_data => :environment do
172
172
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
173
- config = connect_to_database
174
- next unless config
173
+ assure_data_schema_table
175
174
  past_migrations[0..(step - 1)].each do | past_migration |
176
175
  if past_migration[:kind] == :data
177
176
  ActiveRecord::Migration.write("== %s %s" % ['Data', "=" * 71])
@@ -187,6 +186,7 @@ namespace :db do
187
186
  namespace :forward do
188
187
  desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
189
188
  task :with_data => :environment do
189
+ assure_data_schema_table
190
190
  # TODO: No worky for .forward
191
191
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
192
192
  # DataMigrate::DataMigrator.forward('db/data/', step)
@@ -206,6 +206,7 @@ namespace :db do
206
206
  namespace :version do
207
207
  desc "Retrieves the current schema version numbers for data and schema migrations"
208
208
  task :with_data => :environment do
209
+ assure_data_schema_table
209
210
  puts "Current Schema version: #{ActiveRecord::Migrator.current_version}"
210
211
  puts "Current Data version: #{DataMigrate::DataMigrator.current_version}"
211
212
  end
@@ -214,6 +215,7 @@ end
214
215
 
215
216
  namespace :data do
216
217
  task :migrate => :environment do
218
+ assure_data_schema_table
217
219
  ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
218
220
  DataMigrate::DataMigrator.migrate("db/data/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
219
221
  end
@@ -221,6 +223,7 @@ namespace :data do
221
223
  namespace :migrate do
222
224
  desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
223
225
  task :redo => :environment do
226
+ assure_data_schema_table
224
227
  if ENV["VERSION"]
225
228
  Rake::Task["data:migrate:down"].invoke
226
229
  Rake::Task["data:migrate:up"].invoke
@@ -232,6 +235,7 @@ namespace :data do
232
235
 
233
236
  desc 'Runs the "up" for a given migration VERSION.'
234
237
  task :up => :environment do
238
+ assure_data_schema_table
235
239
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
236
240
  raise "VERSION is required" unless version
237
241
  DataMigrate::DataMigrator.run(:up, "db/data/", version)
@@ -241,6 +245,7 @@ namespace :data do
241
245
  task :down => :environment do
242
246
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
243
247
  raise "VERSION is required" unless version
248
+ assure_data_schema_table
244
249
  DataMigrate::DataMigrator.run(:down, "db/data/", version)
245
250
  end
246
251
 
@@ -277,14 +282,16 @@ namespace :data do
277
282
 
278
283
  desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
279
284
  task :rollback => :environment do
285
+ assure_data_schema_table
280
286
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
281
287
  DataMigrate::DataMigrator.rollback('db/data/', step)
282
288
  end
283
289
 
284
290
  desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
285
291
  task :forward => :environment do
286
- # TODO: No worky for .forward
292
+ assure_data_schema_table
287
293
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
294
+ # TODO: No worky for .forward
288
295
  # DataMigrate::DataMigrator.forward('db/data/', step)
289
296
  migrations = pending_data_migrations.reverse.pop(step).reverse
290
297
  migrations.each do | pending_migration |
@@ -294,6 +301,7 @@ namespace :data do
294
301
 
295
302
  desc "Retrieves the current schema version number for data migrations"
296
303
  task :version => :environment do
304
+ assure_data_schema_table
297
305
  puts "Current data version: #{DataMigrate::DataMigrator.current_version}"
298
306
  end
299
307
  end
@@ -342,3 +350,16 @@ def past_migrations sort=nil
342
350
 
343
351
  sort == 'asc' ? sort_migrations(migrations) : sort_migrations(migrations).reverse
344
352
  end
353
+
354
+ def assure_data_schema_table
355
+ config = ActiveRecord::Base.configurations[Rails.env || 'development']
356
+ ActiveRecord::Base.establish_connection(config)
357
+ sm_table = DataMigrate::DataMigrator.schema_migrations_table_name
358
+
359
+ unless ActiveRecord::Base.connection.table_exists?(sm_table)
360
+ ActiveRecord::Base.connection.create_table(sm_table, :id => false) do |schema_migrations_table|
361
+ schema_migrations_table.column :version, :string, :null => false
362
+ end
363
+ ActiveRecord::Base.connection.add_index sm_table, :version, :unique => true, :name => "#{ActiveRecord::Base.table_name_prefix}unique_data_migrations#{ActiveRecord::Base.table_name_suffix}"
364
+ end
365
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: data_migrate
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.0
5
+ version: 1.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Andrew J Vargo
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-02 00:00:00 Z
13
+ date: 2011-05-05 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -47,9 +47,6 @@ files:
47
47
  - lib/data_migrate/railtie.rb
48
48
  - lib/data_migrate/version.rb
49
49
  - lib/generators/data_migrate.rb
50
- - lib/generators/data_migrate/USAGE
51
- - lib/generators/data_migrate/install/install_generator.rb
52
- - lib/generators/data_migrate/install/templates/install_migration.rb
53
50
  - lib/generators/data_migration/data_migration_generator.rb
54
51
  - lib/generators/data_migration/templates/data_migration.rb
55
52
  - lib/generators/data_migration/templates/migration.rb
@@ -1,8 +0,0 @@
1
- Description:
2
- Explain the generator
3
-
4
- Example:
5
- rails generate data_migration Thing
6
-
7
- This will create:
8
- what/will/it/create
@@ -1,24 +0,0 @@
1
- require 'generators/data_migrate'
2
- require 'rails/generators'
3
- require 'rails/generators/migration'
4
-
5
- module DataMigrate
6
- module Generators
7
- class InstallGenerator < Rails::Generators::Base
8
- include Rails::Generators::Migration
9
-
10
- def create_migration_file
11
- migration_template "install_migration.rb", "db/migrate/create_data_migrations.rb"
12
- end
13
-
14
- protected
15
- def self.next_migration_number(dirname)
16
- if ActiveRecord::Base.timestamped_migrations
17
- Time.new.utc.strftime("%Y%m%d%H%M%S")
18
- else
19
- "%.3d" % (current_migration_number(dirname) + 1)
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,13 +0,0 @@
1
- class CreateDataMigrations < ActiveRecord::Migration
2
- def self.up
3
- create_table :data_migrations do |t|
4
- t.string :version, :null => false
5
- end
6
-
7
- add_index :data_migrations, :version, :unique => true, :name => "<%= ActiveRecord::Base.table_name_prefix %>unique_data_migrations<%= ActiveRecord::Base.table_name_suffix %>"
8
- end
9
-
10
- def self.down
11
- drop_table :data_migrations
12
- end
13
- end