From 0cae7c60ac6e6209c3d9a7cc64ad2298b7e27fe4 Mon Sep 17 00:00:00 2001 From: Aleksey Magusev Date: Sun, 8 Jul 2012 17:01:49 +0400 Subject: Add references statements to migration generator AddXXXToYYY/RemoveXXXFromYYY migrations are produced with references statements, for instance rails g migration AddReferencesToProducts user:references supplier:references{polymorphic} will generate the migration with: add_reference :products, :user, index: true add_reference :products, :supplier, polymorphic: true, index: true --- .../active_record/migration/templates/migration.rb | 20 ++++++++++++--- railties/CHANGELOG.md | 11 ++++++++ .../test/generators/migration_generator_test.rb | 29 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb b/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb index b1a0f83b5f..34eaffcb0f 100644 --- a/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration/templates/migration.rb @@ -2,30 +2,42 @@ class <%= migration_class_name %> < ActiveRecord::Migration <%- if migration_action == 'add' -%> def change <% attributes.each do |attribute| -%> + <%- if attribute.reference? -%> + add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %> + <%- else -%> add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %> <%- if attribute.has_index? -%> add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> <%- end -%> + <%- end -%> <%- end -%> end <%- else -%> def up <% attributes.each do |attribute| -%> - <%- if migration_action -%> - <%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %> +<%- if migration_action -%> + <%- if attribute.reference? -%> + remove_reference :<%= table_name %>, :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %> + <%- else -%> + remove_column :<%= table_name %>, :<%= attribute.name %> <%- end -%> +<%- end -%> <%- end -%> end def down <% attributes.reverse.each do |attribute| -%> - <%- if migration_action -%> +<%- if migration_action -%> + <%- if attribute.reference? -%> + add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %> + <%- else -%> add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %> <%- if attribute.has_index? -%> add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %> <%- end -%> <%- end -%> +<%- end -%> <%- end -%> end <%- end -%> -end +end \ No newline at end of file diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 7223270210..5165d9401f 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,5 +1,16 @@ ## Rails 4.0.0 (unreleased) ## +* The migration generator will now produce AddXXXToYYY/RemoveXXXFromYYY migrations with references statements, for instance + + rails g migration AddReferencesToProducts user:references supplier:references{polymorphic} + + will generate the migration with: + + add_reference :products, :user, index: true + add_reference :products, :supplier, polymorphic: true, index: true + + *Aleksey Magusev* + * Allow scaffold/model/migration generators to accept a `polymorphic` modifier for `references`/`belongs_to`, for instance diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index b320e40654..86e3793289 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -76,6 +76,23 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end end + def test_remove_migration_with_references_options + migration = "remove_references_from_books" + run_generator [migration, "author:belongs_to", "distributor:references{polymorphic}"] + + assert_migration "db/migrate/#{migration}.rb" do |content| + assert_method :up, content do |up| + assert_match(/remove_reference :books, :author/, up) + assert_match(/remove_reference :books, :distributor, polymorphic: true/, up) + end + + assert_method :down, content do |down| + assert_match(/add_reference :books, :author, index: true/, down) + assert_match(/add_reference :books, :distributor, polymorphic: true, index: true/, down) + end + end + end + def test_add_migration_with_attributes_and_indices migration = "add_title_with_index_and_body_to_posts" run_generator [migration, "title:string:index", "body:text", "user_id:integer:uniq"] @@ -138,6 +155,18 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end end + def test_add_migration_with_references_options + migration = "add_references_to_books" + run_generator [migration, "author:belongs_to", "distributor:references{polymorphic}"] + + assert_migration "db/migrate/#{migration}.rb" do |content| + assert_method :change, content do |up| + assert_match(/add_reference :books, :author, index: true/, up) + assert_match(/add_reference :books, :distributor, polymorphic: true, index: true/, up) + end + end + end + def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove migration = "create_books" run_generator [migration, "title:string", "content:text"] -- cgit v1.2.3 From 07ebc53d339a3f59f038c0b2663416c64a417885 Mon Sep 17 00:00:00 2001 From: Aleksey Magusev Date: Sun, 8 Jul 2012 17:20:43 +0400 Subject: Update migrations guide Add a paragraph about references statements in migration generator and the subchapter "Supported type modifiers" --- guides/source/migrations.textile | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/guides/source/migrations.textile b/guides/source/migrations.textile index 342b5a4d57..06e85e5914 100644 --- a/guides/source/migrations.textile +++ b/guides/source/migrations.textile @@ -111,6 +111,7 @@ Active Record provides methods that perform common data definition tasks in a database independent way (you'll read about them in detail later): * +add_column+ +* +add_reference+ * +add_index+ * +change_column+ * +change_table+ @@ -120,6 +121,7 @@ database independent way (you'll read about them in detail later): * +remove_column+ * +remove_index+ * +rename_column+ +* +remove_reference+ If you need to perform tasks specific to your database (for example create a "foreign key":#active-record-and-referential-integrity constraint) then the @@ -332,6 +334,51 @@ NOTE: The generated migration file for destructive migrations will still be old-style using the +up+ and +down+ methods. This is because Rails needs to know the original data types defined when you made the original changes. +Also the generator accepts column type as +references+(also available as +belongs_to+), for instance + + +$ rails generate migration AddUserRefToProducts user:references + + +generates + + +class AddUserRefToProducts < ActiveRecord::Migration + def change + add_reference :products, :user, :index => true + end +end + + +This migration will create a user_id column and appropriate index. + +h4. Supported type modifiers + +You can also specify some options just after the field type between curly braces. You can use the +following modifiers: + +* +limit+ Sets the maximum size of the +string/text/binary/integer+ fields +* +precision+ Defines the precision for the +decimal+ fields +* +scale+ Defines the scale for the +decimal+ fields +* +polymorphic+ Adds a +type+ column for +belongs_to+ associations + +For instance running + + +$ rails generate migration AddDetailsToProducts price:decimal{5,2} supplier:references{polymorphic} + + +will produce a migration that looks like this + + +class AddDetailsToProducts < ActiveRecord::Migration + def change + add_column :products, :price, :precision => 5, :scale => 2 + add_reference :products, :user, :polymorphic => true, :index => true + end +end + + h3. Writing a Migration Once you have created your migration using one of the generators it's time to -- cgit v1.2.3