data_migrator 1.7 → 1.8

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.
@@ -1,73 +1,101 @@
1
1
  require "benchmark"
2
+ require 'extensions/railties/engine'
3
+ require 'extensions/railties/engine/configuration'
2
4
 
3
5
  class DataMigrationTask < Rails::Railtie
4
6
  rake_tasks do
5
- Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
7
+ Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |f| load f }
6
8
  end
7
9
  end
8
10
 
9
11
  module RussellEdge
10
12
  class DataMigrator
11
13
  REMOVE_FILES_REGEX = /^\./
12
-
14
+
13
15
  class << self
16
+ def migrations_path
17
+ "#{Rails.root}/db/data_migrations/"
18
+ end
19
+
20
+ def migrations(path)
21
+ files = Dir["#{path}/**/[0-9]*_*.rb" ]
22
+
23
+ seen = Hash.new false
24
+
25
+ migrations = files.map do |file|
26
+ version, name = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?.rb/).first
27
+
28
+ raise ActiveRecord::IllegalMigrationNameError.new(file) unless version
29
+ version = version.to_i
30
+ name = name.camelize
31
+
32
+ raise ActiveRecord::DuplicateMigrationVersionError.new(version) if seen[version]
33
+ raise ActiveRecord::DuplicateMigrationNameError.new(name) if seen[name]
34
+
35
+ seen[version] = seen[name] = true
36
+
37
+ {:name => File.basename(file), :filename => file, :version => version}
38
+ end
39
+
40
+ migrations.sort{|h| h[:version]}
41
+ end
42
+
14
43
  def next_migration_number
15
- Time.now.utc.strftime("%Y%m%d%H%M%S")
44
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
16
45
  end
17
-
46
+
18
47
  def initialize_data_migrations_table
19
48
  puts "** data_migrations table missing creating now...."
20
- puts ActiveRecord::Migrator.run(:up, File.join(File.dirname(__FILE__),'../db/migrate/'), 20100819181805)
49
+ puts ActiveRecord::Migrator.run(:up, File.join(File.dirname(__FILE__), '../db/migrate/'), 20100819181805)
21
50
  puts "** done"
22
51
  end
23
-
24
- def prepare_migrations
25
- target = "#{Rails.root}/db/data_migrations/"
26
52
 
27
- # first copy all app data_migrations away
28
- files = Dir["#{target}*.rb"]
53
+ def copy(destination, sources, options = {})
54
+ copied = []
29
55
 
30
- unless files.empty?
31
- FileUtils.mkdir_p "#{target}/ignore/app/"
32
- FileUtils.cp files, "#{target}/ignore/app/"
33
- puts "copied #{files.size} data_migrations to db/data_migrations/ignore/app"
34
- end
56
+ FileUtils.mkdir_p(destination) unless File.exists?(destination)
35
57
 
36
- dirs = Rails::Application::Railties.engines.map{|p| p.config.root.to_s}
37
- files = Dir["{#{dirs.join(',')}}/db/data_migrations/*.rb"]
58
+ destination_migrations = migrations(destination)
59
+ last = destination_migrations.last
60
+ sources.each do |scope, path|
61
+ source_migrations = migrations(path)
38
62
 
39
- unless files.empty?
40
- FileUtils.mkdir_p target
41
- FileUtils.cp files, target
42
- puts "copied #{files.size} migrations to db/data_migrations"
43
- end
44
- end
63
+ source_migrations.each do |migration|
45
64
 
46
- def cleanup_migrations
47
- target = "#{Rails.root}/db/data_migrations/"
65
+ source = File.read(migration[:filename])
66
+ source = "# This migration comes from #{scope} (originally #{migration[:version]})\n#{source}"
48
67
 
49
- files = Dir["#{target}*.rb"]
50
- unless files.empty?
51
- FileUtils.rm files
52
- puts "removed #{files.size} data_migrations from db/data_migrations"
53
- end
54
- files = Dir["#{target}/ignore/app/*.rb"]
55
- unless files.empty?
56
- FileUtils.cp files, target
57
- puts "copied #{files.size} data_migrations back to db/data_migrations"
68
+ if duplicate = destination_migrations.detect { |m| m[:name] == migration[:name] }
69
+ if options[:on_skip] && duplicate.scope != scope.to_s
70
+ options[:on_skip].call(scope, migration)
71
+ end
72
+ next
73
+ end
74
+
75
+ migration[:version] = next_migration_number().to_i
76
+ new_path = File.join(destination, "#{File.basename(migration[:filename], '.*')}.#{scope}.rb")
77
+ old_path, migration[:filename] = migration[:filename], new_path
78
+
79
+ File.open(migration[:filename], "w") { |f| f.write source }
80
+ copied << migration
81
+ options[:on_copy].call(scope, migration, old_path) if options[:on_copy]
82
+ destination_migrations << migration
83
+ end
58
84
  end
59
- FileUtils.rm_rf "#{target}/ignore/app"
85
+
86
+ copied
60
87
  end
88
+
61
89
  end
62
-
90
+
63
91
  def initialize(migrations_path=nil)
64
92
  @default_migrations_path = migrations_path || "#{Rails.root}/db/data_migrations"
65
93
  end
66
-
94
+
67
95
  def migrate(passed_location=nil, passed_version=nil)
68
96
  setup
69
-
70
- location = passed_location.nil? ? @default_migrations_path : passed_location
97
+
98
+ location = passed_location.nil? ? @default_migrations_path : passed_location
71
99
  @@current_version = get_current_version
72
100
 
73
101
  if passed_version.nil? || @@current_version.nil?
@@ -78,12 +106,12 @@ module RussellEdge
78
106
  handle_higher_passed_version(passed_version)
79
107
  end
80
108
  end
81
-
109
+
82
110
  def pending_migrations
83
111
  versions = []
84
112
  files = get_all_files
85
113
  files.each do |file|
86
- filename, version, klass_name = seperate_file_parts(file)
114
+ filename, version, klass_name = separate_file_parts(file)
87
115
  versions << filename unless version_has_been_migrated?(version)
88
116
  end
89
117
 
@@ -99,64 +127,64 @@ module RussellEdge
99
127
 
100
128
  current_version
101
129
  end
102
-
130
+
103
131
  def run_up(passed_version)
104
132
  setup
105
-
133
+
106
134
  raise "VERSION is required" unless passed_version
107
-
135
+
108
136
  files = get_all_files
109
137
  found = false
110
-
138
+
111
139
  files.each do |file|
112
- filename, version, klass_name = seperate_file_parts(file)
140
+ filename, version, klass_name = separate_file_parts(file)
113
141
  if passed_version == version
114
142
  found = true
115
143
  (version_has_been_migrated?(version)) ? (puts "** Version #{passed_version} has already been migrated") : handle_action(file, klass_name, version, :up)
116
144
  end
117
145
  end
118
-
146
+
119
147
  puts "** Version #{passed_version} not found" unless found
120
-
148
+
121
149
  end
122
-
150
+
123
151
  def run_down(passed_version)
124
152
  setup
125
-
153
+
126
154
  raise "VERSION is required" unless passed_version
127
-
155
+
128
156
  files = get_all_files
129
- found = false
157
+ found = false
130
158
 
131
159
  files.each do |file|
132
- filename, version, klass_name = seperate_file_parts(file)
160
+ filename, version, klass_name = separate_file_parts(file)
133
161
  if passed_version == version
134
162
  found = true
135
163
  (version_has_been_migrated?(version)) ? handle_action(file, klass_name, version, :down) : (puts "** Version #{passed_version} has not been migrated")
136
164
  end
137
165
  end
138
-
166
+
139
167
  puts "** Version #{passed_version} not found" unless found
140
-
168
+
141
169
  end
142
-
170
+
143
171
  private
144
-
172
+
145
173
  def setup
146
174
  RussellEdge::DataMigrator.initialize_data_migrations_table unless data_migrations_table_exists?
147
-
148
- unless File.directory? @default_migrations_path
149
- FileUtils.mkdir_p( @default_migrations_path)
175
+
176
+ unless File.directory? @default_migrations_path
177
+ FileUtils.mkdir_p(@default_migrations_path)
150
178
  #create ignore folder
151
- FileUtils.mkdir_p(File.join(@default_migrations_path,'ignore/'))
179
+ FileUtils.mkdir_p(File.join(@default_migrations_path, 'ignore/'))
152
180
  end
153
181
  end
154
-
182
+
155
183
  def handle_higher_passed_version(passed_version)
156
184
  files = get_all_files
157
185
 
158
186
  files.each do |file|
159
- filename, version, klass_name = seperate_file_parts(file)
187
+ filename, version, klass_name = separate_file_parts(file)
160
188
  if version <= passed_version
161
189
  unless version_has_been_migrated?(version)
162
190
  handle_action(file, klass_name, version, :up)
@@ -170,9 +198,9 @@ module RussellEdge
170
198
  files = get_all_files
171
199
 
172
200
  files.each do |file|
173
- filename, version, klass_name = seperate_file_parts(file)
201
+ filename, version, klass_name = separate_file_parts(file)
174
202
  if passed_version.nil? or version <= passed_version
175
- if !version_has_been_migrated?(version)
203
+ if !version_has_been_migrated?(version)
176
204
  handle_action(file, klass_name, version, :up)
177
205
  end
178
206
  end
@@ -183,7 +211,7 @@ module RussellEdge
183
211
  files = get_all_files
184
212
 
185
213
  files.each do |file|
186
- filename, version, klass_name = seperate_file_parts(file)
214
+ filename, version, klass_name = separate_file_parts(file)
187
215
  if version > passed_version
188
216
  handle_action(file, klass_name, version, :down) if version_has_been_migrated?(version)
189
217
  end
@@ -201,16 +229,15 @@ module RussellEdge
201
229
  klass.send(action.to_s)
202
230
  end
203
231
  end
204
- rescue Exception=>ex
205
- RussellEdge::DataMigrator.cleanup_migrations
232
+ rescue Exception => ex
206
233
  raise ex
207
234
  end
208
235
  time_str = "(%.4fs)" % time.real
209
236
  puts "================Finished #{klass.to_s} in #{time_str}=="
210
-
237
+
211
238
  (action == :up) ? insert_migration_version(version) : remove_migration_version(version)
212
239
  end
213
-
240
+
214
241
  def insert_migration_version(version)
215
242
  ActiveRecord::Base.connection.execute("insert into data_migrations (version) values ('#{version}')")
216
243
  end
@@ -225,42 +252,43 @@ module RussellEdge
225
252
  db_result = ActiveRecord::Base.connection.select_all("select count(*) as num_rows from data_migrations where version = '#{version}'")
226
253
 
227
254
  num_rows = db_result[0]['num_rows'] unless db_result == -1
228
-
255
+
229
256
  result = false if (num_rows.nil? || num_rows.to_i == 0)
230
257
  result
231
258
  end
232
259
 
233
260
  def data_migrations_table_exists?
234
- table_names = ActiveRecord::Base.connection.tables
261
+ table_names = ActiveRecord::Base.connection.tables
235
262
  table_names.include?('data_migrations')
236
263
  end
237
264
 
238
- def seperate_file_parts(file)
265
+ def separate_file_parts(file)
239
266
  paths = file.split('/')
240
267
  filename = paths[paths.length - 1]
241
268
  version = filename.split('_')[0]
242
269
  klass_name = filename.gsub(/#{version}/, "").gsub(/.rb/, "")[1..filename.length]
270
+ klass_name = klass_name.split('.')[0] if klass_name.split('.').length > 1 #check for scope of engine name
243
271
 
244
272
  return filename, version.to_i, klass_name
245
273
  end
246
274
 
247
275
  def get_all_files
248
276
  files = []
249
-
277
+
250
278
  if File.directory? @default_migrations_path
251
-
252
- files_or_directories = Dir.entries(@default_migrations_path).map{|directory| directory}
253
279
 
254
- files_or_directories.delete_if{|name| name =~ REMOVE_FILES_REGEX} #remove any file leading with . or ..
255
- files_or_directories.delete_if{|name| name == 'ignore'} #ignore the ignore folder
280
+ files_or_directories = Dir.entries(@default_migrations_path).map { |directory| directory }
281
+
282
+ files_or_directories.delete_if { |name| name =~ REMOVE_FILES_REGEX } #remove any file leading with . or ..
283
+ files_or_directories.delete_if { |name| name == 'ignore' } #ignore the ignore folder
284
+
256
285
 
257
-
258
286
  files_or_directories.each do |file_or_directory|
259
287
  file_or_directory = @default_migrations_path + "/" + file_or_directory
260
288
  files = get_files_in_directory(file_or_directory, files)
261
289
  end
262
290
 
263
- files.sort! {|x,y| File.basename(x) <=> File.basename(y)}
291
+ files.sort! { |x, y| File.basename(x) <=> File.basename(y) }
264
292
  end
265
293
 
266
294
  files
@@ -268,10 +296,10 @@ module RussellEdge
268
296
 
269
297
  def get_files_in_directory(file_or_directory, files)
270
298
  unless file_or_directory =~ /\w\.rb/
271
- files_or_directories = Dir.entries(file_or_directory).map{|directory| directory}
299
+ files_or_directories = Dir.entries(file_or_directory).map { |directory| directory }
272
300
 
273
- files_or_directories.delete_if{|name| name =~ REMOVE_FILES_REGEX} #remove any file leading with . or ..
274
- files_or_directories.delete_if{|name| name == 'ignore'} #ignore the ignore folder
301
+ files_or_directories.delete_if { |name| name =~ REMOVE_FILES_REGEX } #remove any file leading with . or ..
302
+ files_or_directories.delete_if { |name| name == 'ignore' } #ignore the ignore folder
275
303
 
276
304
  files_or_directories.each do |_file_or_directory|
277
305
  _file_or_directory = file_or_directory + "/" + _file_or_directory
@@ -0,0 +1,23 @@
1
+ Rails::Engine.class_eval do
2
+ rake_tasks do
3
+ next if self.is_a?(Rails::Application)
4
+ next unless has_data_migrations?
5
+
6
+ namespace railtie_name do
7
+ namespace :install do
8
+ desc "Copy data_migrations from #{railtie_name} to application"
9
+ task :data_migrations do
10
+ ENV["FROM"] = railtie_name
11
+ Rake::Task["railties:install:data_migrations"].invoke
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ def has_data_migrations?
20
+ paths["db/data_migrations"].existent.any?
21
+ end
22
+
23
+ end
@@ -0,0 +1,30 @@
1
+ Rails::Engine::Configuration.class_eval do
2
+ def paths
3
+ @paths ||= begin
4
+ paths = Rails::Paths::Root.new(@root)
5
+ paths.add "app", :eager_load => true, :glob => "*"
6
+ paths.add "app/assets", :glob => "*"
7
+ paths.add "app/controllers", :eager_load => true
8
+ paths.add "app/helpers", :eager_load => true
9
+ paths.add "app/models", :eager_load => true
10
+ paths.add "app/mailers", :eager_load => true
11
+ paths.add "app/views"
12
+ paths.add "lib", :load_path => true
13
+ paths.add "lib/assets", :glob => "*"
14
+ paths.add "lib/tasks", :glob => "**/*.rake"
15
+ paths.add "config"
16
+ paths.add "config/environments", :glob => "#{Rails.env}.rb"
17
+ paths.add "config/initializers", :glob => "**/*.rb"
18
+ paths.add "config/locales", :glob => "*.{rb,yml}"
19
+ paths.add "config/routes", :with => "config/routes.rb"
20
+ paths.add "db"
21
+ paths.add "db/migrate"
22
+ paths.add "db/data_migrations"
23
+ paths.add "db/seeds", :with => "db/seeds.rb"
24
+ paths.add "vendor", :load_path => true
25
+ paths.add "vendor/assets", :glob => "*"
26
+ paths.add "vendor/plugins"
27
+ paths
28
+ end
29
+ end
30
+ end
@@ -2,20 +2,16 @@ namespace :db do
2
2
  desc 'migrates data into database'
3
3
  task :migrate_data => :environment do
4
4
  passed_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
5
- RussellEdge::DataMigrator.prepare_migrations
5
+
6
6
  RussellEdge::DataMigrator.new.migrate(nil, passed_version)
7
- RussellEdge::DataMigrator.cleanup_migrations
8
-
9
7
  end#end migrate_data task
10
8
 
11
9
  namespace :migrate_data do
12
10
  task :list_pending => :environment do
13
- RussellEdge::DataMigrator.prepare_migrations
14
11
  pending_migrations = RussellEdge::DataMigrator.new.pending_migrations
15
12
  puts "================Pending Data Migrations=========="
16
13
  puts pending_migrations
17
14
  puts "================================================="
18
- RussellEdge::DataMigrator.cleanup_migrations
19
15
  end#end list_pending task
20
16
 
21
17
  task :version => :environment do
@@ -26,23 +22,44 @@ namespace :db do
26
22
  task :up => :environment do
27
23
  passed_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
28
24
  raise "VERSION is required" unless passed_version
29
-
30
- RussellEdge::DataMigrator.prepare_migrations
25
+
31
26
  RussellEdge::DataMigrator.new.run_up(passed_version)
32
- RussellEdge::DataMigrator.cleanup_migrations
33
-
34
27
  end#end up task
35
28
 
36
29
  task :down => :environment do
37
30
  passed_version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
38
31
  raise "VERSION is required" unless passed_version
39
-
40
- RussellEdge::DataMigrator.prepare_migrations
32
+
41
33
  RussellEdge::DataMigrator.new.run_down(passed_version)
42
- RussellEdge::DataMigrator.cleanup_migrations
43
-
44
34
  end#end down task
45
35
  end#end namespace
46
36
  end
47
37
 
38
+ namespace :railties do
39
+ namespace :install do
40
+ # desc "Copies missing data_migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
41
+ task :data_migrations => :environment do
42
+ to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
43
+ railties = ActiveSupport::OrderedHash.new
44
+ Rails.application.railties.all do |railtie|
45
+ next unless to_load == :all || to_load.include?(railtie.railtie_name)
46
+
47
+ if railtie.respond_to?(:paths) && (path = railtie.paths['db/data_migrations'].first)
48
+ railties[railtie.railtie_name] = path
49
+ end
50
+ end
51
+
52
+ on_skip = Proc.new do |name, migration|
53
+ puts "NOTE: Data Migration #{migration[:name]} from #{name} has been skipped. Migration with the same name already exists."
54
+ end
55
+
56
+ on_copy = Proc.new do |name, migration, old_path|
57
+ puts "Copied data_migration #{migration[:name]} from #{name}"
58
+ end
59
+
60
+ RussellEdge::DataMigrator.copy(RussellEdge::DataMigrator.migrations_path, railties, :on_skip => on_skip, :on_copy => on_copy)
61
+ end
62
+ end
63
+ end
64
+
48
65
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_migrator
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.7'
4
+ version: '1.8'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,19 +9,19 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-26 00:00:00.000000000Z
12
+ date: 2012-10-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: activerecord
16
- requirement: &2157691620 !ruby/object:Gem::Requirement
15
+ name: rails
16
+ requirement: &70230211897860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 2.3.5
21
+ version: '2.3'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2157691620
24
+ version_requirements: *70230211897860
25
25
  description: Allows you to create data migrations that can be run up and down to insert
26
26
  data into the database.
27
27
  email: russellfholmes@gmail.com
@@ -31,6 +31,8 @@ extra_rdoc_files: []
31
31
  files:
32
32
  - db/migrate/20100819181805_create_data_migrations_table.rb
33
33
  - lib/data_migrator.rb
34
+ - lib/extensions/railties/engine/configuration.rb
35
+ - lib/extensions/railties/engine.rb
34
36
  - lib/generators/data_migration/data_migration_generator.rb
35
37
  - lib/generators/data_migration/templates/migration_template.rb
36
38
  - lib/generators/data_migration/USAGE
@@ -59,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
61
  version: '0'
60
62
  requirements: []
61
63
  rubyforge_project:
62
- rubygems_version: 1.8.6
64
+ rubygems_version: 1.8.11
63
65
  signing_key:
64
66
  specification_version: 3
65
67
  summary: Creates Data Migrations for data similar to schema migrations.