Why directly changing a migrate file does not change the schema file? - ruby-on-rails

My current migrate file is
class CreateMovies < ActiveRecord::Migration
def up
create_table :movies, :force => true do |t|
t.string :title
t.string :rating
t.text :description
t.datetime :release_date
# Add fields that let Rails automatically keep track
# of when movies are added or modified:
t.timestamps
end
end
def down
drop_table :movies
end
end
I try to change release_date type to integer. So I directly change the file to
class CreateMovies < ActiveRecord::Migration
def up
create_table :movies, :force => true do |t|
t.string :title
t.string :rating
t.text :description
t.integer :release_date
# Add fields that let Rails automatically keep track
# of when movies are added or modified:
t.timestamps
end
end
def down
drop_table :movies
end
end
Please pay attention, the release_date type has been changed. But after I run
bundle exec rake db:migrate
It still produce the same schema file as before. I am so confused.

It's probably because you've already run your migration. So before you want to change it, you should rollback it first:
bundle exec rake db:rollback
then you should modify it and run again:
bundle exec rake db:migrate

As an alternative to dropping and upping the migration, you could make a new migration to change the column type.
class ChangeMoviesReleaseTypeToInteger < ActiveRecord::Migration
def up
change_column :movies, :release_date, :integer
end
def down
change_column :movies, :release_date, :datetime
end
end
Just as a side note, release_date is a confusing name for an integer field - most people would expect it to be a datetime as you had originally.

down will remove the table
rake db:migrate:down VERSION=file_name(exclude extension)
up will create with new changes
rake db:migrate:up VERSION=file_name(exclude extension)

Related

Rails 4: Re-Migrating all Migrations to Schema

I am currently developing an Rails 4 app and over the last few months I collected a lot of unique migration files, which reverse their own changes, etc.
Since I have no problem to reset the db at this stage of development, I thought I could might clean up this mess a bit.Is there a way of redoing all migration files, while also allowing to delete certain migration-files and to expand others?
I appreciate each answer!
Example (Edit)
I have two migration files:
20160911071103_create_items.rb
20160918085621_add_cached_votes_to_items.rb
Both are already migrated.<
1st file before
class CreateItems < ActiveRecord::Migration
def change
create_table :items do |t|
t.integer :user_id
t.timestamps null: false
end
end
end
My goal is to include the added column by the second file directly in the first file and deleting the second.
1st file after
class CreateItems < ActiveRecord::Migration
def change
create_table :items do |t|
t.integer :user_id
t.integer :cached_votes
t.timestamps null: false
end
end
end
You need to run
rake db:migrate:down VERSION=20160918085621
rake db:migrate:down VERSION=20160911071103
You can now check the migration status by rake db:migrate:status and you should expect to get migration status as follows:
down 20160911071103
down 20160918085621
Now, you can remove the migration file 20160918085621_add_cached_votes_to_items.rb
& edit the migration file 20160911071103_create_items.rb as you need.
And, finally run:
rake db:migrate:up VERSION=20160911071103
As you are saying you it's on development only so you can change the migration files.
NOTE: It is not recommended to edit your migration but as it's not deployed anywhere so you can do it.
20160911071103_create_items.rb
class CreateItems < ActiveRecord::Migration
def change
create_table :items do |t|
t.integer :user_id
t.timestamps null: false
end
end
end
20160918085621_add_cached_votes_to_items.rb
class AddCachedVotesToItems < ActiveRecord::Migration
def change
add_column :items, :cached_votes, :integer
end
end
Modify your first migration and remember to delete second migration.
20160911071103_create_items.rb (Migration 1 + Migration 2)
class CreateItems < ActiveRecord::Migration
def change
create_table :items do |t|
t.integer :user_id
t.integer :cached_votes
t.timestamps null: false
end
end
end
And then Drop and Migrate again
rake db:drop # Drop the db
rake db:setup # Create and migrate the db
if you have a working schema.rb file. you can just generate a migration file
bundle exec rails generate migration CreateItemsNew
Then fill the codeblock create_table "items" from your working schema.rb to this newly generated migration file. Then do a bulk search for all the migrations in your db/migrate that changes the table items and delete those files. This way you'll have a single migration file for a table in your db.

change column name Rails

I have this table:
class CreateShoes < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.boolean :leather
t.integer :season
t.timestamps null: false
end
end
end
the 'season' column should be called 'season_id'. I know that I have to write 't.rename :season, :season_id' as explained in http://edgeguides.rubyonrails.org/active_record_migrations.html#column-modifiers but I don't manage to find the right syntax. Should it be?
class CreateShoes < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.boolean :leather
t.integer :season
t.timestamps null: false
end
change_table :products do |t|
t.rename :season, :season_id
end
end
end
Doesn't work. Anything I have to do in the Mac console? Thanks!
Run in your console:
$ rails g migration rename_season_to_season_id
Now file db/migrate/TIMESTAMP_rename_season_to_season_id.rb contains following:
class RenameSeasonToSeasonId < ActiveRecord::Migration
def change
end
end
Modify it as follows:
class RenameSeasonToSeasonId < ActiveRecord::Migration
def change
rename_column :shoes, :season, :season_id
end
end
Then run $ rake db:migrate in console.
Either fix your migration and do
rake db:rollback db:migrate
or make another migration like so:
rename_column :shoes, :season, :season_id if column_exists?(:shoes, :season) && !column_exists?(:shoes, :season_id)
and then do
rake db:migrate
If your intention is to rename column in table than you example migration is not making sense :)... Instead of this
class CreateShoes < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.boolean :leather
t.integer :season
t.timestamps null: false
end
change_table :products do |t|
t.rename :season, :season_id
end
end
end
You just need table change migration, like this(Rails will take care rollback for your):
class RenameSessionColumnInsideShoes < ActiveRecord::Migration
def change
change_table :products do |t|
t.rename :season, :season_id
end
end
end
rename method on table object in rails is valid method, as you can see in Rails source code
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L582
If your branch has been pushed to production then one probably needs to add the new migration by running the following command:
rails g migration RenameSeasonColumnNameToShoes
and if it hasn't been pushed to production or you have to currently make changes to your branch only, then do:
bundle exec rake db:rollback
Then make changes to your migration file inside /db/migrate/<your_migration_file_name>
Then in your migration file, using rename_column do as follows:
class RenameSeasonColumnNameToShoes < ActiveRecord::Migration
def change
rename_column :shoes, :season, :season_id
end
end
and then do
bundle exec rake db:migrate db:test:prepare

How do you migrate db structure changes to heroku postgres?

For example, I have a migration file for posts:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.text :text
t.integer :ip
t.timestamps
end
end
end
And want to change it to:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.text :text
t.integer :ip, :limit => 8
t.timestamps
end
end
end
Would I add a line:
change_column :posts, :ip, :limit => 8
Below so that the file is:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.text :text
t.integer :ip, :limit => 8
t.timestamps
change_column :posts, :ip, :limit => 8
end
end
end
And then run heroku run rake --trace db:migrate
I'm having trouble understanding how migrations work, and especially to production, so any help would be greatly appreciated.
There is http://guides.rubyonrails.org/active_record_migrations.html#changing-columns a section 3.5 on column modifiers but it doesn't specify how to pass them.
Thanks!
You should create a separate migration for adding the limit on the ip column.
Generate your migration:
rails generate migration ChangeIpLimitOnPosts
Inside the generated migration file, update the contents:
class ChangeIpLimitOnPosts < ActiveRecord::Migration
def up
change_column :posts, :ip, :integer, limit: 8
end
def down
change_column :posts, :ip, :integer
end
end
Take note here: you need to specify the column type when changing the column, even though in your case, you're not changing the type.
Also, in this case, Active Record will not know how to reverse the transaction if you need to rollback, so you need to explicitly tell Active Record how to do that — this can be done using the up and down methods, rather than change.
Run your migration:
rake db:migrate
On Heroku:
heroku run rake db:migrate
Hope that helps.

How can I add new attributes into my migrate?

I currently have the migrate thing like:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.string :encrypted_password
t.string :salt
t.timestamps
end
end
end
now, if I wanna add two new attributes into this file, one is: t.string :type , and the other one is: t.string :memory_token , how can I do this please?
If you have already run the migration you will have to create a new one.
rails g migration AddTypeToUsers
And then in the migration file you can edit in
change_table :users do |t|
t.string :type
t.string :memory_token
end
Then run a migration rake db:migrate to make the changes
If you haven't run the migration then you can simply add
t.string :type
t.string :memory_token
To that file you have showed us and then run your migration
+1 to #JTG
You can also make this just with one line:
rails g migration AddTypeAndMemoryTokenToUsers type:string memory_token:string
and you will get a following file:
class AddTypeAndMemoryTokenToUsers < ActiveRecord::Migration
def change
add_column :users, :type, :string
add_column :users, :memory_token, :string
end
end
which will make the changes after running rake db:migrate

No output after running rake db:migrate

I'm struggling here with the db migration for the acts_as_commentable_with_threading.
After generating the migration rails generate acts_as_commentable_with_threading_migration I proceeded to add the comment table rake db:migrate. Nothing happened, no error message, just returned to the regular prompt.
Looking at other response to this problem I tried rake db:migrate VERSION= # version number.
Yet here I get an Error response ActiveRecord::UnknownMigrationVersionError:
I must be doing something extremely wrong here since the computer doesn't validate the existence of my comment migration...
UPDATE from #Tiago answer
Ran rails generate migration acts_as_commentable_with_threading_migration
I had to manually create the migration by adding this code to the migration file. Then, thedb:migration worked perfectly.
Why wasn't it working in the first place? The Documentation clearly indicate to run rails generate acts_as_commentable_with_threading_migration.
Just create a migration for yourself as indicated in the gem's page:
rails g migration acts_as_commentable_with_threading_migration
And paste that to the file:
class ActsAsCommentableWithThreadingMigration < ActiveRecord::Migration
def self.up
create_table :comments, :force => true do |t|
t.integer :commentable_id, :default => 0
t.string :commentable_type
t.string :title
t.text :body
t.string :subject
t.integer :user_id, :default => 0, :null => false
t.integer :parent_id, :lft, :rgt
t.timestamps
end
add_index :comments, :user_id
add_index :comments, [:commentable_id, :commentable_type]
end
def self.down
drop_table :comments
end
end

Resources