Permalink
Browse files

Merge pull request #8652 from codeodor/create_table_migration

Support creating a table migration generator

Sometimes you want to create a table without an associated model and
test, which is also not a join table. With this commit, you can now
do that.

Example:

    rails g migration create_posts title:string
or
    rails g migration CreatePosts title:string

This commit also moves the template the model generator uses for the
migration to the migration templates folder, as it seems a more
sensible place for it now that it is shared code.
  • Loading branch information...
2 parents bb9f831 + 20e0415 commit b49a2a779ba6deba108d1f842ab5b7bc7460aa14 @carlosantoniodasilva carlosantoniodasilva committed Mar 1, 2013
View
@@ -1,5 +1,15 @@
## Rails 4.0.0 (unreleased) ##
+* Added support for creating a table via Rails migration generator.
+ For example,
+
+ rails g migration create_books title:string content:text
+
+ will generate a migration that creates a table called books with
+ the listed attributes, without creating a model.
+
+ *Sammy Larbi*
+
* Fix bug that raises the wrong exception when the exception handled by PostgreSQL adapter
doesn't respond to `#result`.
Fixes #8617.
@@ -362,7 +372,7 @@
deprecated and removed in future versions of Rails.
*Amparo Luna + Guillermo Iguaran*
-
+
* `after_commit` and `after_rollback` now validate the `:on` option and raise an `ArgumentError`
if it is not one of `:create`, `:destroy` or `:update`
@@ -1549,4 +1559,5 @@
*Aaron Patterson*
+
Please check [3-2-stable](https://github.com/rails/rails/blob/3-2-stable/activerecord/CHANGELOG.md) for previous changes.
@@ -8,13 +8,14 @@ class MigrationGenerator < Base # :nodoc:
def create_migration_file
set_local_assigns!
validate_file_name!
- migration_template "migration.rb", "db/migrate/#{file_name}.rb"
+ migration_template @migration_template, "db/migrate/#{file_name}.rb"
end
protected
attr_reader :migration_action, :join_tables
def set_local_assigns!
+ @migration_template = "migration.rb"
case file_name
when /^(add|remove)_.*_(?:to|from)_(.*)/
@migration_action = $1
@@ -26,6 +27,9 @@ def set_local_assigns!
set_index_names
end
+ when /^create_(.+)/
+ @table_name = $1.pluralize
+ @migration_template = "create_table_migration.rb"
end
end
@@ -44,7 +48,10 @@ def index_name_for(attribute)
end
private
-
+ def attributes_with_index
+ attributes.select { |a| !a.reference? && a.has_index? }
+ end
+
def validate_file_name!
unless file_name =~ /^[_a-z0-9]+$/
raise IllegalMigrationNameError.new(file_name)
@@ -15,7 +15,7 @@ class ModelGenerator < Base # :nodoc:
def create_migration_file
return unless options[:migration] && options[:parent].nil?
attributes.each { |a| a.attr_options.delete(:index) if a.reference? && !a.has_index? } if options[:indexes] == false
- migration_template "migration.rb", "db/migrate/create_#{table_name}.rb"
+ migration_template "../../migration/templates/create_table_migration.rb", "db/migrate/create_#{table_name}.rb"
end
def create_model_file
@@ -179,6 +179,27 @@ class AddDetailsToProducts < ActiveRecord::Migration
end
```
+If the migration name is of the form "CreateXXX" and is
+followed by a list of column names and types then a migration creating the table
+XXX with the columns listed will be generated. For example:
+
+```bash
+$ rails generate migration CreateProducts name:string part_number:string
+```
+
+generates
+
+```ruby
+class CreateProducts < ActiveRecord::Migration
+ def change
+ create_table :products do |t|
+ t.string :name
+ t.string :part_number
+ end
+ end
+end
+```
+
As always, what has been generated for you is just a starting point. You can add
or remove from it as you see fit by editing the
`db/migrate/YYYYMMDDHHMMSS_add_details_to_products.rb` file.
@@ -172,8 +172,19 @@ def test_create_join_table_migration
end
end
- def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove
- migration = "create_books"
+ def test_create_table_migration
+ run_generator ["create_books", "title:string", "content:text"]
+ assert_migration "db/migrate/create_books.rb" do |content|
+ assert_method :change, content do |change|
+ assert_match(/create_table :books/, change)
+ assert_match(/ t\.string :title/, change)
+ assert_match(/ t\.text :content/, change)
+ end
+ end
+ end
+
+ def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove_or_create
+ migration = "delete_books"
run_generator [migration, "title:string", "content:text"]
assert_migration "db/migrate/#{migration}.rb" do |content|
@@ -182,7 +193,7 @@ def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove
end
end
end
-
+
def test_properly_identifies_usage_file
assert generator_class.send(:usage_path)
end

0 comments on commit b49a2a7

Please sign in to comment.