migrant 1.5.0 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -29
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -5
  5. data/Gemfile +3 -4
  6. data/LICENSE.txt +21 -0
  7. data/{README.rdoc → README.md} +57 -57
  8. data/Rakefile +4 -31
  9. data/VERSION +1 -1
  10. data/lib/dsl/data_type.rb +5 -1
  11. data/lib/dsl/data_types/primitives.rb +11 -0
  12. data/lib/generators/templates/change_migration.erb +1 -1
  13. data/lib/generators/templates/create_migration.erb +1 -1
  14. data/lib/generators/templates/create_migration.rb +1 -1
  15. data/lib/migrant/migration_generator.rb +10 -6
  16. data/lib/migrant/model_extensions.rb +1 -1
  17. data/lib/migrant/schema.rb +0 -2
  18. data/lib/railtie.rb +2 -2
  19. data/lib/tasks/db.rake +0 -6
  20. data/migrant.gemspec +30 -31
  21. metadata +63 -193
  22. data/.rvmrc +0 -1
  23. data/LICENSE +0 -20
  24. data/lib/simple_object.rb +0 -13
  25. data/test/additional_models/review.rb +0 -11
  26. data/test/helper.rb +0 -64
  27. data/test/rails_app/.gitignore +0 -4
  28. data/test/rails_app/README +0 -256
  29. data/test/rails_app/Rakefile +0 -7
  30. data/test/rails_app/app/controllers/application_controller.rb +0 -3
  31. data/test/rails_app/app/helpers/application_helper.rb +0 -2
  32. data/test/rails_app/app/models/business.rb +0 -25
  33. data/test/rails_app/app/models/business_category.rb +0 -6
  34. data/test/rails_app/app/models/category.rb +0 -10
  35. data/test/rails_app/app/models/chameleon.rb +0 -5
  36. data/test/rails_app/app/models/customer.rb +0 -9
  37. data/test/rails_app/app/models/non_migrant_model.rb +0 -3
  38. data/test/rails_app/app/models/user.rb +0 -8
  39. data/test/rails_app/app/views/layouts/application.html.erb +0 -14
  40. data/test/rails_app/config.ru +0 -4
  41. data/test/rails_app/config/application.rb +0 -16
  42. data/test/rails_app/config/boot.rb +0 -13
  43. data/test/rails_app/config/database.yml +0 -7
  44. data/test/rails_app/config/environment.rb +0 -5
  45. data/test/rails_app/config/environments/development.rb +0 -26
  46. data/test/rails_app/config/environments/production.rb +0 -49
  47. data/test/rails_app/config/environments/test.rb +0 -35
  48. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  49. data/test/rails_app/config/initializers/inflections.rb +0 -10
  50. data/test/rails_app/config/initializers/mime_types.rb +0 -5
  51. data/test/rails_app/config/initializers/secret_token.rb +0 -7
  52. data/test/rails_app/config/initializers/session_store.rb +0 -8
  53. data/test/rails_app/config/locales/en.yml +0 -5
  54. data/test/rails_app/config/routes.rb +0 -58
  55. data/test/rails_app/db/seeds.rb +0 -7
  56. data/test/rails_app/lib/tasks/.gitkeep +0 -0
  57. data/test/rails_app/public/404.html +0 -26
  58. data/test/rails_app/public/422.html +0 -26
  59. data/test/rails_app/public/500.html +0 -26
  60. data/test/rails_app/script/rails +0 -6
  61. data/test/rails_app/test/performance/browsing_test.rb +0 -9
  62. data/test/rails_app/test/test_helper.rb +0 -13
  63. data/test/rails_app/vendor/plugins/.gitkeep +0 -0
  64. data/test/test_data_schema.rb +0 -108
  65. data/test/test_migration_generator.rb +0 -251
  66. data/test/test_validations.rb +0 -49
  67. data/test/test_zzz_performance.rb +0 -13
  68. data/test/verified_output/migrations/added_incompatible_spot_and_deleted_spots.rb +0 -11
  69. data/test/verified_output/migrations/business_id.rb +0 -10
  70. data/test/verified_output/migrations/businesses_indexed_name.rb +0 -8
  71. data/test/verified_output/migrations/chameleons_added_new_longer_spots_and_moved_new_spots.rb +0 -15
  72. data/test/verified_output/migrations/create_business_categories.rb +0 -14
  73. data/test/verified_output/migrations/create_businesses.rb +0 -31
  74. data/test/verified_output/migrations/create_categories.rb +0 -13
  75. data/test/verified_output/migrations/create_chameleons.rb +0 -11
  76. data/test/verified_output/migrations/create_reviews.rb +0 -18
  77. data/test/verified_output/migrations/create_users.rb +0 -19
  78. data/test/verified_output/migrations/created_at.rb +0 -11
  79. data/test/verified_output/migrations/deleted_incompatible_spot.rb +0 -9
  80. data/test/verified_output/migrations/deleted_spots.rb +0 -9
  81. data/test/verified_output/migrations/estimated_value_notes.rb +0 -11
  82. data/test/verified_output/migrations/landline.rb +0 -9
  83. data/test/verified_output/migrations/modified_verified.rb +0 -9
  84. data/test/verified_output/migrations/renamed_old_spots.rb +0 -9
File without changes
@@ -1,108 +0,0 @@
1
- require 'helper'
2
-
3
- def assert_schema(model, name, options = {})
4
- field = model.schema.column_migrations.detect {|m| m.first == name}
5
- assert_not_nil(field, 'Migration was not generated')
6
- options.each do |key, correct_value|
7
- assert_equal(correct_value, field[1][key])
8
- end
9
- end
10
-
11
- class TestDataSchema < Test::Unit::TestCase
12
- context "The schema generator" do
13
- should "generate a foreign key field for a belongs_to association" do
14
- assert_schema(Business, :user_id, :type => :integer)
15
- assert_schema(BusinessCategory, :business_id, :type => :integer)
16
- assert_schema(BusinessCategory, :category_id, :type => :integer)
17
- assert_schema(User, :category_id, :type => :integer)
18
- end
19
-
20
- should "generate foreign key fields for a *polymorphic* belongs_to association" do
21
- assert_schema(Business, :owner_id, :type => :integer)
22
- assert_schema(Business, :owner_type, :type => :string)
23
- end
24
-
25
- should "generate a string column when given a string example" do
26
- assert_schema(Business, :name)
27
- end
28
-
29
- should "generate a datetime column when given a date or time example" do
30
- assert_schema(Business, :date_established, :type => :datetime)
31
- assert_schema(Business, :next_sale, :type => :datetime)
32
- assert_schema(Business, :date_registered, :type => :date)
33
- end
34
-
35
- should "generate a smallint column when given a small range" do
36
- assert_schema(Business, :operating_days, :type => :integer)
37
- end
38
-
39
- should "generate a large integer (size 8) for any bignum types" do
40
- assert_schema(Category, :serial_number, :limit => 8, :type => :integer)
41
- end
42
-
43
- should "generate a string column when given a sentence" do
44
- assert_schema(Business, :summary, :type => :string)
45
- end
46
-
47
- should "generate a text column when given a long paragraph" do
48
- assert_schema(Business, :address, :type => :text)
49
- end
50
-
51
- should "pass on any options provided in a structure block" do
52
- assert_schema(User, :average_rating, :type => :float, :default => 0.0)
53
- end
54
-
55
- should "generate a boolean column when a true or false is given" do
56
- assert_schema(Business, :verified, :type => :boolean)
57
- end
58
-
59
- should "generate a column verbatim if no type is specified" do
60
- assert_schema(Business, :location, :type => :string, :limit => 127)
61
- end
62
-
63
- should "generate a string column when no options are given" do
64
- assert_schema(Category, :title, :type => :string)
65
- assert_schema(Category, :summary, :type => :string)
66
- end
67
-
68
- should "generate a decimal column when a currency is given" do
69
- assert_schema(User, :money_spent, :type => :decimal, :scale => 2)
70
- assert_schema(User, :money_gifted, :type => :decimal, :scale => 2)
71
- end
72
-
73
- should "generate a floating point column when a decimal is given" do
74
- assert_schema(User, :average_rating, :type => :float)
75
- end
76
-
77
- should "generate a string column when an email example or class is given" do
78
- assert_schema(User, :email, :type => :string)
79
- end
80
-
81
- should "generate indexes for all foreign keys automatically" do
82
- assert_contains(Business.schema.indexes, :user_id, 'Missing index on belongs_to')
83
- assert_contains(Business.schema.indexes, [:owner_type, :owner_id], 'Missing index on polymorphic belongs_to')
84
- assert_contains(BusinessCategory.schema.indexes, :business_id, 'Missing index on belongs_to')
85
- assert_contains(BusinessCategory.schema.indexes, :category_id, 'Missing index on belongs_to')
86
- end
87
-
88
- should "generate indexes on any column when explicitly asked to" do
89
- assert_contains(Category.schema.indexes, :title, 'Missing index on :index => true column')
90
- end
91
-
92
- should "generate a text column for serialized fields" do
93
- assert_schema(Business, :awards, :type => :text)
94
- assert_schema(Business, :managers, :type => :text)
95
-
96
- assert_equal(Array, Business.schema.columns[:awards].mock.class)
97
- assert_equal(Hash, Business.schema.columns[:managers].mock.class)
98
-
99
- assert(Business.serialized_attributes.keys.include?("awards"), "Should call ActiveRecord::Base.serialize")
100
- assert(Business.serialized_attributes.keys.include?("managers"), "Should call ActiveRecord::Base.serialize")
101
- end
102
- end
103
-
104
- should "still indicate a structure is not defined if a belongs_to association is added" do
105
- assert_equal(false, NonMigrantModel.structure_defined?)
106
- assert_equal(true, Business.structure_defined?)
107
- end
108
- end
@@ -1,251 +0,0 @@
1
- require 'helper'
2
- require 'rake'
3
-
4
- def rake_migrate
5
- Dir.chdir(Rails.root.join('.')) do
6
- Rake::Task['db:migrate'].execute
7
- end
8
- end
9
-
10
- class TestMigrationGenerator < Test::Unit::TestCase
11
- def generate_migrations
12
- Profiler.run(:migration_generator) do
13
- assert_equal true, Migrant::MigrationGenerator.new.run, "Migration Generator reported an error"
14
- end
15
- end
16
-
17
- def run_against_template(template)
18
- generate_migrations
19
- Dir.glob(File.join(File.dirname(__FILE__), 'rails_app', 'db' ,'migrate', '*.rb')).each do |migration_file|
20
- if migration_file.include?(template)
21
- to_test = File.open(migration_file, 'r') { |r| r.read}.strip
22
- File.open(File.join(File.dirname(__FILE__), 'verified_output', 'migrations', template+'.rb'), 'r') do |file|
23
- while (line = file.gets)
24
- assert_not_nil(to_test.gsub(/[\.\(\)]/, '').match(line.gsub(/[\.\(\)]/, '').strip), "Generated migration #{migration_file} missing line: #{line.gsub(/[\.\(\)]/, '').strip}")
25
- end
26
- end
27
- rake_migrate
28
- return
29
- end
30
- end
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
41
- end
42
-
43
- def delete_last_migration
44
- File.delete(Dir.glob(File.join(File.dirname(__FILE__), 'rails_app', 'db' ,'migrate', '*.rb')).last)
45
- end
46
-
47
- context "The migration generator" do
48
- should "create migrations for all new tables" do
49
- generate_migrations
50
- Dir.glob(File.join(File.dirname(__FILE__), 'rails_app', 'db' ,'migrate', '*.rb')).each do |migration_file|
51
- to_test = File.open(migration_file, 'r') { |r| r.read}.strip
52
- File.open(File.join(File.dirname(__FILE__), 'verified_output', 'migrations', migration_file.sub(/^.*\d+_/, '')), 'r') do |file|
53
- while (line = file.gets)
54
- assert_not_nil(to_test.match(line.strip), "Generated migration #{migration_file} missing line: #{line}")
55
- end
56
- end
57
- end
58
- rake_migrate
59
- end
60
-
61
- should "generate a migration for new added fields" do
62
- Business.structure do
63
- estimated_value 5000.0
64
- notes
65
- end
66
- run_against_template('estimated_value_notes')
67
- end
68
-
69
- should "generate a migration to alter existing columns where no data loss would occur" do
70
- Business.structure do
71
- landline :text
72
- end
73
-
74
- run_against_template('landline')
75
- end
76
-
77
- should "generate a migration to alter existing columns while adding a new table" do
78
- load File.join(File.dirname(__FILE__), 'additional_models', 'review.rb')
79
- User.belongs_to(:business) # To generate a business_id on a User
80
- User.no_structure # To force schema update
81
-
82
- run_against_template('create_reviews')
83
- run_against_template('business_id')
84
- end
85
-
86
- should "generate created_at and updated_at when given the column timestamps" do
87
- Business.structure do
88
- timestamps
89
- end
90
- run_against_template('created_at')
91
- end
92
-
93
- should "prompt the user to confirm changing existing columns where data loss may occur" do
94
- STDIN._mock_responses('N')
95
-
96
- Business.structure do
97
- landline :integer # Was previously a string, which obviously may incur data loss
98
- end
99
- Migrant::MigrationGenerator.new.run
100
- assert(any_template_match?('modified_landline'), 'Ignored a request not to generate a dangerous migration!')
101
- Business.structure do
102
- landline :text # Undo our bad for the next tests
103
- end
104
- end
105
-
106
- should "exit immediately if there are pending migrations" do
107
- manual_migration = Rails.root.join("db/migrate/9999999999999999_my_new_migration.rb")
108
- File.open(manual_migration, 'w') { |f| f.write ' ' }
109
- assert_equal(false, Migrant::MigrationGenerator.new.run)
110
- File.delete(manual_migration)
111
- end
112
-
113
- should "still create sequential migrations for the folks not using timestamps" do
114
- Business.structure do
115
- new_field_i_made_up
116
- end
117
- # Remove migrations
118
- ActiveRecord::Base.timestamped_migrations = false
119
- generate_migrations
120
- ActiveRecord::Base.timestamped_migrations = true
121
-
122
- assert_equal(Dir.glob(File.join(File.dirname(__FILE__), 'rails_app', 'db' ,'migrate', '*.rb')).select { |migration_file| migration_file.include?('new_field_i_made_up') }.length,
123
- 1,
124
- "Migration should have been generated (without a duplicate)")
125
- rake_migrate
126
- end
127
-
128
- should "recursively generate mocks for every model" do
129
- BusinessCategory.structure do
130
- test_mockup_of_text :text
131
- test_mockup_of_string :string
132
- test_mockup_of_integer :integer
133
- test_mockup_of_float :float
134
- test_mockup_of_datetime :datetime
135
- test_mockup_of_currency DataType::Currency
136
- test_mockup_serialized :serialized
137
- test_mockup_hash OpenStruct.new({'a' => 'b'})
138
- test_mockup_serialized_example :serialized, :example => OpenStruct.new({'c' => 'd'})
139
- end
140
-
141
-
142
- BusinessCategory.belongs_to(:notaclass, :polymorphic => true)
143
- generate_migrations
144
- rake_migrate
145
- BusinessCategory.reset_column_information
146
- m = BusinessCategory.mock!
147
- mock = BusinessCategory.last
148
-
149
- assert_not_nil(mock)
150
- assert(mock.test_mockup_of_text.is_a?(String))
151
- assert(mock.test_mockup_of_string.is_a?(String))
152
- assert(mock.test_mockup_of_integer.is_a?(Fixnum))
153
- assert(mock.test_mockup_of_float.is_a?(Float))
154
- assert(mock.test_mockup_of_currency.is_a?(BigDecimal))
155
- assert(mock.test_mockup_of_datetime.is_a?(Time))
156
- assert(DataType::Base.default_mock.is_a?(String))
157
- assert(mock.test_mockup_serialized.is_a?(Hash))
158
- assert(mock.test_mockup_hash.is_a?(OpenStruct))
159
- assert_equal(mock.test_mockup_hash.a, 'b')
160
- assert(mock.test_mockup_serialized_example.is_a?(OpenStruct))
161
- assert_equal(mock.test_mockup_serialized_example.c, 'd')
162
- end
163
-
164
- should "not rescursively generate mocks for an inherited model when prohibited by the user" do
165
- category_mock = BusinessCategory.mock!({}, false)
166
- assert_not_nil(category_mock)
167
- end
168
-
169
- should "generate example mocks for an inherited model when STI is in effect" do
170
- assert_equal(5.00, Customer.mock.average_rating)
171
- assert_equal("somebody@somewhere.com", Customer.mock.email)
172
- assert(Customer.mock.is_a?(Customer))
173
- end
174
-
175
-
176
- should "remove columns when requested and confirmed by the user" do
177
- Chameleon.structure
178
- Chameleon.reset_structure!
179
- Chameleon.no_structure
180
-
181
- STDIN._mock_responses('D', 'y')
182
- run_against_template('deleted_incompatible_spot')
183
- end
184
-
185
- should "not remove columns when the user does not confirm" do
186
- Chameleon.reset_structure!
187
- Chameleon.no_structure
188
-
189
- STDIN._mock_responses('D', 'n')
190
- generate_migrations
191
- rake_migrate
192
- Chameleon.structure do
193
- spots
194
- end
195
- end
196
-
197
- should "successfully rename a column missing from the schema to a new column specified by the user" do
198
- Chameleon.structure do
199
- old_spots
200
- end
201
- generate_migrations
202
- rake_migrate
203
- Chameleon.reset_structure!
204
- Chameleon.structure do
205
- new_spots
206
- end
207
- STDIN._mock_responses('M', 'new_spots')
208
- run_against_template('renamed_old_spots')
209
- end
210
-
211
- should "transfer data to an new incompatible column if the operation is safe" do
212
- Chameleon.reset_column_information
213
- Chameleon.create!(:new_spots => "22")
214
- Chameleon.reset_structure!
215
- Chameleon.structure do
216
- new_longer_spots "100", :as => :text
217
- end
218
- STDIN._mock_responses('M', 'new_longer_spots', 'M')
219
- run_against_template('chameleons_added_new_longer_spots_and_moved_new_spots')
220
- Chameleon.reset_column_information
221
- assert_equal(Chameleon.first.new_longer_spots, "22")
222
- end
223
-
224
- should "remove any column if a user elects to when a column can't be moved due to incompatible types" do
225
- Chameleon.reset_structure!
226
- Chameleon.structure do
227
- incompatible_spot 5
228
- end
229
-
230
- STDIN._mock_responses('M', 'incompatible_spot', 'N', 'Y')
231
- run_against_template('added_incompatible_spot_and_deleted_spots')
232
- end
233
-
234
- should "update a column to include a new default" do
235
- Business.structure do
236
- verified true, :default => true
237
- end
238
-
239
- run_against_template('modified_verified')
240
- end
241
-
242
- should "update indexes on a model" do
243
- Business.structure do
244
- name "The Kernel's favourite fried chickens.", :index => true
245
- end
246
-
247
- run_against_template('businesses_indexed_name')
248
- end
249
- end
250
- end
251
-
@@ -1,49 +0,0 @@
1
- require 'helper'
2
-
3
- class TestValidations < Test::Unit::TestCase
4
- should "validate via ActiveRecord when the validates symbol is supplied" do
5
- Business.structure do
6
- website :string, :validates => :presence
7
- end
8
-
9
- business = Business.create
10
- assert(business.errors.include?(:website), "Validation was not applied")
11
- end
12
-
13
- should "validate via ActiveRecord when the full validation hash is supplied" do
14
- Category.structure do
15
- summary :string, :validates => { :format => { :with => /Symphony\d/ } }
16
- end
17
-
18
- bad_category = Category.create
19
- good_category = Category.create(:summary => "Symphony5")
20
- assert(bad_category.errors.include?(:summary), "Validation was not applied")
21
- assert(!good_category.errors.include?(:summary), "Validation options were incorrect")
22
- end
23
-
24
- should "validate via ActiveRecord when no field name is given" do
25
- User.structure do
26
- email :validates => :presence
27
- end
28
-
29
- user = User.create
30
- assert(user.errors.include?(:email), "Validation was not applied")
31
- end
32
-
33
- should "validate multiple validations via ActiveRecord when an array is given" do
34
- Review.structure do
35
- name "ABCD", :validates => [:presence, {:length => {:maximum => 4}}]
36
- end
37
-
38
- not_present = Review.create
39
- too_long = Review.create(:name => "Textthatistoolong")
40
- correct = Review.create(:name => "ABC")
41
-
42
- assert(not_present.errors.include?(:name), "primary validation was not applied")
43
- assert(too_long.errors.include?(:name), "secondary validation was not applied")
44
- assert(!correct.errors.include?(:name), "validation for a correct model failed")
45
-
46
- end
47
-
48
- end
49
-
@@ -1,13 +0,0 @@
1
- require 'helper'
2
-
3
- #SimpleProfiler.results
4
-
5
- class TestZZZPerformance < Test::Unit::TestCase
6
- context "Performance" do
7
- should "be within acceptable limits" do
8
- # Just a utility test for printing profiler results
9
- Profiler.results
10
- assert true
11
- end
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- class ChangedChameleonsAddedIncompatibleSpotAndDeletedSpots < ActiveRecord::Migration
2
- def self.up
3
- add_column :chameleons, :incompatible_spot, :integer
4
- remove_column :chameleons, :spots
5
- end
6
-
7
- def self.down
8
- add_column :chameleons, :spots, :string, :limit=>255
9
- remove_column :chameleons, :incompatible_spot
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- class ChangedUsersAddedBusinessId < ActiveRecord::Migration
2
- def self.up
3
- add_column :users, :business_id, :integer
4
- add_index :users, :business_id
5
- end
6
-
7
- def self.down
8
- remove_column :users, :business_id
9
- end
10
- end