migrant 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - rbx-18mode
7
+ - ree
data/README.rdoc CHANGED
@@ -1,12 +1,13 @@
1
1
  = Migrant
2
+ {<img src="https://secure.travis-ci.org/pascalh1011/migrant.png" />}[http://travis-ci.org/pascalh1011/migrant]
2
3
 
3
4
  == Summary
4
5
 
5
- Migrant gives you a clean DSL to describe your model schema (somewhat similar to DataMapper)
6
- that generates your migrations for you and enables you to spend more time on describing your domain
6
+ Migrant gives you a clean DSL to describe your model schema (somewhat similar to DataMapper).
7
+ It generates your migrations for you so you can spend more time describing your domain
7
8
  model cleanly and less time managing your database layer.
8
9
 
9
- You'll also get a handy .mock method to instantiate a filled in model for testing or debugging purposes.
10
+ You'll also get a handy .mock method to instantiate a filled-in model for testing or debugging.
10
11
 
11
12
  == Getting Started
12
13
 
@@ -14,9 +15,9 @@ In your Gemfile:
14
15
 
15
16
  gem "migrant"
16
17
 
17
- Rails: 3.0+ (Sorry folks, no plans for Rails 2 support)
18
- Ruby: Tested with 1.8.7 MRI, 1.9.2 MRI, and Rubinius 1.2.1
19
- Adapters: Tested with SQLite3, MySQL, MySQL2, Pg. Should work with any AR adapter in theory.
18
+ * Rails: 3.0+ (Sorry folks, no plans for Rails 2 support)
19
+ * Ruby: Tested with 1.8.7 MRI, 1.9.2 MRI, and Rubinius 1.2.1
20
+ * Adapters: Tested with SQLite3, MySQL, MySQL2, Pg. Should work with any AR adapter in theory.
20
21
 
21
22
  == Jumping right in
22
23
 
@@ -105,7 +106,7 @@ These will call ActiveRecord::Base.serialize for you so don't do it again yourse
105
106
 
106
107
  == Want more examples?
107
108
 
108
- Check out the test models in test/rails_app/app/models/*
109
+ Check out the test models in +test/rails_app/app/models/*+
109
110
 
110
111
  == Model Generator
111
112
 
@@ -125,12 +126,6 @@ Simply run rake db:upgrade or rails generate migrations to get the required migr
125
126
  * Changing column types
126
127
  * Rollbacks for all the above
127
128
 
128
- == What won't
129
-
130
- These actions won't be performed (because we don't want to hurt your data):
131
-
132
- * Changing column types where data loss may occur (e.g. varchar -> int)
133
-
134
129
  == Getting a mock of your model
135
130
 
136
131
  > rails console
@@ -194,7 +189,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
194
189
 
195
190
  Please be sure to install all the development dependencies via Bundler, then to run tests do:
196
191
 
197
- > rake test
192
+ > rake test
198
193
 
199
- Simplecov reports will be generated for each run, if it's not at 100% line coverage, something's wrong!
194
+ Simplecov reports will be generated for each run. If it's not at 100% line coverage, something's wrong!
200
195
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.0
1
+ 1.3.1
data/lib/dsl/data_type.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  require 'faker'
2
2
 
3
3
  module DataType
4
- class DangerousMigration < Exception; end;
5
-
6
4
  class Base
7
5
  attr_accessor :aliases
8
6
 
@@ -59,8 +57,6 @@ module DataType
59
57
 
60
58
  if current_structure
61
59
  # General RDBMS data loss scenarios
62
- raise DataType::DangerousMigration if (new_structure[:type] != :text && [:string, :text].include?(current_structure[:type]) && new_structure[:type] != current_structure[:type])
63
-
64
60
  if new_structure[:limit] && current_structure[:limit].to_i != new_structure[:limit].to_i ||
65
61
  new_structure[:type] != current_structure[:type]
66
62
  column
@@ -72,10 +68,12 @@ module DataType
72
68
  end
73
69
  end
74
70
 
71
+ def dangerous_migration_from?(current_structure = nil)
72
+ current_structure && (column[:type] != :text && [:string, :text].include?(current_structure[:type]) && column[:type] != current_structure[:type])
73
+ end
74
+
75
75
  def self.migrant_data_type?; true; end
76
76
  end
77
-
78
-
79
77
  end
80
78
 
81
79
  require 'dsl/data_types/primitives'
@@ -26,6 +26,9 @@ module Migrant
26
26
  end
27
27
  end
28
28
 
29
+ # Rails 3.2+ caches table (non) existence so this needs to be cleared before we start
30
+ ActiveRecord::Base.connection.schema_cache.clear! if ActiveRecord::Base.connection.respond_to?(:schema_cache)
31
+
29
32
  ActiveRecord::Base.descendants.select { |model| model.schema && model.schema.requires_migration? }.each do |model|
30
33
  model.reset_column_information # db:migrate doesn't do this
31
34
  @table_name = model.table_name
@@ -35,17 +38,15 @@ module Migrant
35
38
  # Structure ActiveRecord::Base's column information so we can compare it directly to the schema
36
39
  db_schema = Hash[*model.columns.collect {|c| [c.name.to_sym, Hash[*[:type, :limit].map { |type| [type, c.send(type)] }.flatten] ] }.flatten]
37
40
  model.schema.columns.to_a.sort { |a,b| a.to_s <=> b.to_s }.each do |field_name, data_type|
38
- begin
39
- if (options = data_type.structure_changes_from(db_schema[field_name]))
40
- if db_schema[field_name]
41
- change_column(field_name, options, db_schema[field_name])
42
- else
43
- add_column(field_name, options)
44
- end
41
+ if data_type.dangerous_migration_from?(db_schema[field_name]) &&
42
+ ask_user("#{model}: '#{field_name}': Converting from ActiveRecord type #{db_schema[field_name][:type]} to #{data_type.column[:type]} could cause data loss. Continue?", %W{Yes No}, true) == "No"
43
+ log "Aborting dangerous action on #{field_name}."
44
+ elsif (options = data_type.structure_changes_from(db_schema[field_name]))
45
+ if db_schema[field_name]
46
+ change_column(field_name, options, db_schema[field_name])
47
+ else
48
+ add_column(field_name, options)
45
49
  end
46
- rescue DataType::DangerousMigration
47
- log "Cannot generate migration automatically for #{model.table_name}, this would involve possible data loss on column: #{field_name}\nOld structure: #{db_schema[field_name].inspect}. New structure: #{data_type.column.inspect}\nPlease create and run this migration yourself (with the appropriate data integrity checks)", :error
48
- return false
49
50
  end
50
51
  end
51
52
 
@@ -57,10 +58,11 @@ module Migrant
57
58
  when 'Move' then
58
59
  target = ask_user("Move '#{removed_field_name}' to:", @columns[:added].collect(&:first))
59
60
  target_column = model.schema.columns[target]
60
- begin
61
+
62
+ unless target_column.dangerous_migration_from?(db_schema[removed_field_name])
61
63
  target_column.structure_changes_from(db_schema[removed_field_name])
62
64
  move_column(removed_field_name, target, db_schema[removed_field_name], target_column)
63
- rescue DataType::DangerousMigration
65
+ else
64
66
  case ask_user("Unable to safely move '#{removed_field_name}' to '#{target}'. Keep the original column for now?", %W{Yes No}, true)
65
67
  when 'No' then delete_column(removed_field_name, db_schema[removed_field_name])
66
68
  end
@@ -89,7 +91,7 @@ module Migrant
89
91
  # Example: changed_table_added_something_and_modified_something
90
92
  @activity = 'changed_'+model.table_name+[['added', @columns[:added]], ['modified', @columns[:changed]], ['deleted', destroyed_columns],
91
93
  ['moved', @columns[:transferred]], ['renamed', @columns[:renamed]], ['indexed', @new_indexes]].reject { |v| v[1].empty? }.collect { |v| "_#{v[0]}_"+v[1].collect(&:first).join('_') }.join('_and')
92
- @activity = @activity.split('_')[0..2].join('_') if @activity.length >= 240 # Most filesystems will raise Errno::ENAMETOOLONG otherwise
94
+ @activity = @activity.split('_')[0..2].join('_')+'_with_multiple_changes' if @activity.length >= 240 # Most filesystems will raise Errno::ENAMETOOLONG otherwise
93
95
 
94
96
  render('change_migration')
95
97
  else
data/migrant.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Pascal Houliston"]
9
9
  s.date = %q{2011-05-23}
10
- s.description = %q{Easier schema management for Rails that compliments your domain model.}
10
+ s.description = %q{Easier schema management for Rails that complements your domain model.}
11
11
  s.email = %q{101pascal@gmail.com}
12
12
  s.extra_rdoc_files = [
13
13
  "LICENSE",
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.homepage = %q{http://github.com/pascalh1011/migrant}
20
20
  s.require_paths = ["lib"]
21
21
  s.rubygems_version = %q{1.5.2}
22
- s.summary = %q{All the fun of ActiveRecord, without writing your migrations, and a dash of mocking.}
22
+ s.summary = %q{All the fun of ActiveRecord without writing your migrations, and with a dash of mocking.}
23
23
 
24
24
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
25
25
  s.add_development_dependency(%q<minitest>, [">= 1.6.0"])
data/test/helper.rb CHANGED
@@ -61,7 +61,7 @@ Dir.glob(File.join(File.dirname(__FILE__), 'rails_app', 'db', 'migrate', '*')).e
61
61
  File.delete(file)
62
62
  end
63
63
 
64
- require File.join(File.dirname(__FILE__), 'rails_app', 'config', 'environment')
64
+ #require File.join(File.dirname(__FILE__), 'rails_app', 'config', 'environment')
65
65
 
66
66
  class Test::Unit::TestCase
67
67
  end
@@ -28,7 +28,16 @@ class TestMigrationGenerator < Test::Unit::TestCase
28
28
  return
29
29
  end
30
30
  end
31
- flunk "No migration could be found"
31
+ flunk "No migration could be found like '#{template}'"
32
+ end
33
+
34
+ def any_template_match?(template)
35
+ Dir.glob(File.join(File.dirname(__FILE__), 'rails_app', 'db' ,'migrate', '*.rb')).each do |migration_file|
36
+ if migration_file.include?(template)
37
+ return true
38
+ end
39
+ end
40
+ false
32
41
  end
33
42
 
34
43
  def delete_last_migration
@@ -81,11 +90,14 @@ class TestMigrationGenerator < Test::Unit::TestCase
81
90
  run_against_template('created_at')
82
91
  end
83
92
 
84
- should "not change existing columns where data loss may occur" do
93
+ should "prompt the user to confirm changing existing columns where data loss may occur" do
94
+ STDIN._mock_responses('N')
95
+
85
96
  Business.structure do
86
97
  landline :integer # Was previously a string, which obviously may incur data loss
87
98
  end
88
- assert_equal(false, Migrant::MigrationGenerator.new.run, "MigrationGenerator ran a dangerous migration!")
99
+ Migrant::MigrationGenerator.new.run
100
+ assert(any_template_match?('modified_landline'), 'Ignored a request not to generate a dangerous migration!')
89
101
  Business.structure do
90
102
  landline :text # Undo our bad for the next tests
91
103
  end
@@ -161,20 +173,6 @@ class TestMigrationGenerator < Test::Unit::TestCase
161
173
  end
162
174
 
163
175
 
164
- should "remove extraneous text from a filename too large for the operating system" do
165
- BusinessCategory.structure do
166
- a_very_very_long_field_indeed_far_too_long_for_any_good_use_really true
167
- a_very_very_long_field_indeed_far_too_long_for_any_good_use_really_2 true
168
- a_very_very_long_field_indeed_far_too_long_for_any_good_use_really_3 true
169
- end
170
-
171
- BusinessCategory.belongs_to(:verylongclassthatissuretogenerateaverylargeoutputfilename)
172
- generate_migrations
173
- delete_last_migration # Can't actually test migration because the index name is too long!
174
- # BusinessCategory.schema.undo_structure_column(:verylongclassthatissuretogenerateaverylargeoutputfilename_id)
175
- BusinessCategory.reset_structure!
176
- end
177
-
178
176
  should "remove columns when requested and confirmed by the user" do
179
177
  Chameleon.structure
180
178
  Chameleon.reset_structure!
metadata CHANGED
@@ -1,172 +1,170 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: migrant
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.1
4
5
  prerelease:
5
- version: 1.3.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Pascal Houliston
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-05-23 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
12
+ date: 2011-05-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
16
15
  name: thoughtbot-shoulda
17
- prerelease: false
18
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &74513810 !ruby/object:Gem::Requirement
19
17
  none: false
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
24
22
  type: :development
25
- version_requirements: *id001
26
- - !ruby/object:Gem::Dependency
27
- name: minitest
28
23
  prerelease: false
29
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *74513810
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ requirement: &74513520 !ruby/object:Gem::Requirement
30
28
  none: false
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
34
32
  version: 1.6.0
35
33
  type: :development
36
- version_requirements: *id002
37
- - !ruby/object:Gem::Dependency
38
- name: ansi
39
34
  prerelease: false
40
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *74513520
36
+ - !ruby/object:Gem::Dependency
37
+ name: ansi
38
+ requirement: &74513240 !ruby/object:Gem::Requirement
41
39
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- version: "0"
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
46
44
  type: :development
47
- version_requirements: *id003
48
- - !ruby/object:Gem::Dependency
49
- name: turn
50
45
  prerelease: false
51
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *74513240
47
+ - !ruby/object:Gem::Dependency
48
+ name: turn
49
+ requirement: &74512790 !ruby/object:Gem::Requirement
52
50
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: "0"
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
57
55
  type: :development
58
- version_requirements: *id004
59
- - !ruby/object:Gem::Dependency
60
- name: sqlite3
61
56
  prerelease: false
62
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *74512790
58
+ - !ruby/object:Gem::Dependency
59
+ name: sqlite3
60
+ requirement: &74512220 !ruby/object:Gem::Requirement
63
61
  none: false
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: "0"
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
68
66
  type: :development
69
- version_requirements: *id005
70
- - !ruby/object:Gem::Dependency
71
- name: simplecov
72
67
  prerelease: false
73
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *74512220
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: &74511770 !ruby/object:Gem::Requirement
74
72
  none: false
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- version: "0"
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
79
77
  type: :development
80
- version_requirements: *id006
81
- - !ruby/object:Gem::Dependency
82
- name: terminal-table
83
78
  prerelease: false
84
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *74511770
80
+ - !ruby/object:Gem::Dependency
81
+ name: terminal-table
82
+ requirement: &74511520 !ruby/object:Gem::Requirement
85
83
  none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: "0"
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
90
88
  type: :development
91
- version_requirements: *id007
92
- - !ruby/object:Gem::Dependency
93
- name: term-ansicolor
94
89
  prerelease: false
95
- requirement: &id008 !ruby/object:Gem::Requirement
90
+ version_requirements: *74511520
91
+ - !ruby/object:Gem::Dependency
92
+ name: term-ansicolor
93
+ requirement: &74511130 !ruby/object:Gem::Requirement
96
94
  none: false
97
- requirements:
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- version: "0"
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
101
99
  type: :development
102
- version_requirements: *id008
103
- - !ruby/object:Gem::Dependency
104
- name: rake
105
100
  prerelease: false
106
- requirement: &id009 !ruby/object:Gem::Requirement
101
+ version_requirements: *74511130
102
+ - !ruby/object:Gem::Dependency
103
+ name: rake
104
+ requirement: &74510740 !ruby/object:Gem::Requirement
107
105
  none: false
108
- requirements:
109
- - - ">="
110
- - !ruby/object:Gem::Version
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
111
109
  version: 0.8.7
112
110
  type: :development
113
- version_requirements: *id009
114
- - !ruby/object:Gem::Dependency
115
- name: simplecov
116
111
  prerelease: false
117
- requirement: &id010 !ruby/object:Gem::Requirement
112
+ version_requirements: *74510740
113
+ - !ruby/object:Gem::Dependency
114
+ name: simplecov
115
+ requirement: &74510150 !ruby/object:Gem::Requirement
118
116
  none: false
119
- requirements:
120
- - - ">="
121
- - !ruby/object:Gem::Version
122
- version: "0"
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
123
121
  type: :development
124
- version_requirements: *id010
125
- - !ruby/object:Gem::Dependency
126
- name: rails
127
122
  prerelease: false
128
- requirement: &id011 !ruby/object:Gem::Requirement
123
+ version_requirements: *74510150
124
+ - !ruby/object:Gem::Dependency
125
+ name: rails
126
+ requirement: &74509790 !ruby/object:Gem::Requirement
129
127
  none: false
130
- requirements:
131
- - - ">="
132
- - !ruby/object:Gem::Version
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
133
131
  version: 3.0.0
134
132
  type: :runtime
135
- version_requirements: *id011
136
- - !ruby/object:Gem::Dependency
137
- name: faker
138
133
  prerelease: false
139
- requirement: &id012 !ruby/object:Gem::Requirement
134
+ version_requirements: *74509790
135
+ - !ruby/object:Gem::Dependency
136
+ name: faker
137
+ requirement: &74509550 !ruby/object:Gem::Requirement
140
138
  none: false
141
- requirements:
142
- - - ">="
143
- - !ruby/object:Gem::Version
144
- version: "0"
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
145
143
  type: :runtime
146
- version_requirements: *id012
147
- - !ruby/object:Gem::Dependency
148
- name: term-ansicolor
149
144
  prerelease: false
150
- requirement: &id013 !ruby/object:Gem::Requirement
145
+ version_requirements: *74509550
146
+ - !ruby/object:Gem::Dependency
147
+ name: term-ansicolor
148
+ requirement: &74509240 !ruby/object:Gem::Requirement
151
149
  none: false
152
- requirements:
153
- - - ">="
154
- - !ruby/object:Gem::Version
155
- version: "0"
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
156
154
  type: :runtime
157
- version_requirements: *id013
158
- description: Easier schema management for Rails that compliments your domain model.
155
+ prerelease: false
156
+ version_requirements: *74509240
157
+ description: Easier schema management for Rails that complements your domain model.
159
158
  email: 101pascal@gmail.com
160
159
  executables: []
161
-
162
160
  extensions: []
163
-
164
- extra_rdoc_files:
161
+ extra_rdoc_files:
165
162
  - LICENSE
166
163
  - README.rdoc
167
- files:
164
+ files:
168
165
  - .gitignore
169
166
  - .rvmrc
167
+ - .travis.yml
170
168
  - Gemfile
171
169
  - LICENSE
172
170
  - README.rdoc
@@ -249,30 +247,27 @@ files:
249
247
  - test/verified_output/migrations/renamed_old_spots.rb
250
248
  homepage: http://github.com/pascalh1011/migrant
251
249
  licenses: []
252
-
253
250
  post_install_message:
254
251
  rdoc_options: []
255
-
256
- require_paths:
252
+ require_paths:
257
253
  - lib
258
- required_ruby_version: !ruby/object:Gem::Requirement
254
+ required_ruby_version: !ruby/object:Gem::Requirement
259
255
  none: false
260
- requirements:
261
- - - ">="
262
- - !ruby/object:Gem::Version
263
- version: "0"
264
- required_rubygems_version: !ruby/object:Gem::Requirement
256
+ requirements:
257
+ - - ! '>='
258
+ - !ruby/object:Gem::Version
259
+ version: '0'
260
+ required_rubygems_version: !ruby/object:Gem::Requirement
265
261
  none: false
266
- requirements:
267
- - - ">="
268
- - !ruby/object:Gem::Version
269
- version: "0"
262
+ requirements:
263
+ - - ! '>='
264
+ - !ruby/object:Gem::Version
265
+ version: '0'
270
266
  requirements: []
271
-
272
267
  rubyforge_project:
273
- rubygems_version: 1.8.5
268
+ rubygems_version: 1.8.16
274
269
  signing_key:
275
270
  specification_version: 3
276
- summary: All the fun of ActiveRecord, without writing your migrations, and a dash of mocking.
271
+ summary: All the fun of ActiveRecord without writing your migrations, and with a dash
272
+ of mocking.
277
273
  test_files: []
278
-