Drop_table problem preventing rake db:migrate - ruby-on-rails

I was looking for a way to drop a table in Rails and start fresh and came across this answer: Rails DB Migration - How To Drop a Table?
However, when I ran drop_table :examples I got the following error:
-bash: drop_table: command not found
Here's my create_examples migrate file:
def self.down
drop_table :examples
end
Can anyone help guide me into fixing this and give me insight on what I'm doing wrong? I need to fix it because this particular migrate is preventing from doing a rake db:migrate, generating the following error:
== CreateExamples: migrating ====================================================
-- create_table(:examples)
rake aborted!
An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: table "examples" already exists: CREATE TABLE "examples" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "content" varchar(255), "user_id" integer, "created_at" datetime, "updated_at" datetime)
Thanks! (And if I need to provide more code let me know.)

You should be dropping your old table right before creating the new version:
def self.up
drop_table :examples
create_table :examples do |t|
#...
end
end
And since you can't really reverse that drop_table, you might want to raise an exception in the rollback:
def self.down
raise ActiveRecord::IrreversibleMigration
end
Or maybe you just want to keep your current self.down.

Related

How to redo a migration in Rails 5 when there is a foreign key involved?

So I have a few connected problems here. So I have begun to add topic back into my app. However when I try to create a new post, I get "Topic must exist". I am not sure what is missing for this to go through specifically.
I do know that I need to somehow redo
AddTopicReferenceToBlogs migration because right now my blogs table looks like this:
create_table "blogs", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.integer "status", default: 0
t.index ["slug"], name: "index_blogs_on_slug", unique: true
end
The t.integer "topic_id" is missing.
I know I cannot rerun AddTopicReferenceToBlogs because I will get an identical.
If I try to do a rake db:migrate:down VERSION=
I get this error:
== 20170725215733 AddTopicReferenceToBlogs: reverting =========================
-- remove_reference(:blogs, :topic, {:foreign_key=>true})
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
Table 'blogs' has no foreign key for {:to_table=>"topics", :column=>"topic_id"}
By the way my Topic.rb file looks like this:
class Topic < ApplicationRecord
validates_presence_of :title
end
There is no quick answer to your problem, but I think what will help you is to understand that you CAN redo AddTopicReferenceToBlogs, you are just going to have to give it a different name.
This documentation speaks to that:
Rails migrations with the same name
Try something like:
rails g migration add_reference_of_topic_to_blogs topic:references
That should work assuming that you haven't screwed up some other migrations in the process as well. Rails migrations can get pretty hairy if you are not sure of what you are doing.
You may still have a problem if this doesn't execute correctly in your dev environment.
rails db:drop db:create db:migrate db:seed
If you just added a new migration to fix the old one, this full database reset may fail because you now have duplicate migrations trying to add_reference :blogs, :topic, .... This will be a problem for your teammates and when you deploy to production.
Assumptions:
You generated an empty migration named AddTopicReferenceToBlogs and ran it with rails db:migrate (or rake db:migrate).
When you checked your schema.rb afterwards, the foreign key you expected to be there (topic_id), wasn't.
You edited the empty migration to add a line that used add_reference and ran rails db:migrate again.
The schema still didn't contain blogs.topic_id.
You tried to rollback the migration with rake db:migrate:down VERSION=??? and it failed (... because you were trying to rollback a migration that never actually ran. Rails can't remove a reference it never added to begin with).
Answer:
Don't add a duplicate migration that does the same thing, but with a different class name.
Comment out the add_reference line in the bad migration AddTopicReferenceToBlogs.
Rollback the empty migration (undo the bad thing you did).
Reactivate the add_reference line.
rake db:migrate again, this time correctly adding the foreign key you expected to schema.rb.
In the future, use this command to generate a pre-filled-in migration for these types of associations.
rails g migration AddTopicToBlog topic:belongs_to
Alternatives:
rails g migration AddTopicToBlogs topic:belongs_to
rails g migration AddTopicToBlog topic:references
rails g migration AddYouCanSayWhateverYouWantHereToBlog topic:references

Rails migration fails creating table in Postgres

As described in the title, I have a migration in my Rails app which creates a table. We have a Postgres database. When I run the migration in development, it fails:
ActiveRecord::StatementInvalid: PG::Error: ERROR: current transaction is aborted, commands ignored until end of transaction block
: CREATE TABLE "feedback_questions" ("id" serial primary key, "survey_id" integer, "question_text" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
The migration is long, but the table creation is the first thing that happens. It looks like this:
def up
create_table :feedback_questions do |t|
t.integer :survey_id
t.text :question_text
t.timestamps
end
# ...
end
It looks to me like this isn't an issue with the migration, but with the database (the error is coming from PG). The error message is similar to this question, but it's not saying anything about what's wrong - just that there's an error. (Also, the table doesn't exist yet; I've checked.)
How can I get more data to debug this?
The error message was a red herring. The issue was not with the table creation; the issue was with the format of the migration itself. I was defining a few models in the migration which used tables created in the #up method. When rake tried to start the migration, it looked for tables for those rows, and flipped when it couldn't find them. The create statement just happened to be the first command not run after the error.

heroku run rake db:migrate gives rake aborted

I'm new to ruby on rails, github and heroku. Now i am doing fixed deposit project in that project i am using database sqlite3 in my localhost and postgres in heroku.
I have add a field called int which datatype is string and i changed the datatype from string to integer. Finally, i decided to change it again from integer to float.
In my local host its working perfecly. But, when i'm trying to run in heroku it shows rake aborted.
heroku run rake db:migrate
it shows the following error message
Running `rake db:migrate` attached to terminal... up, run.4356
Connecting to database specified by DATABASE_URL
Migrating to CreateFds (20140505120047)
Migrating to Changedatatypeforfd (20140506065307)
Migrating to AddMdToFds (20140506080333)
Migrating to AddIntToFds (20140506080404)
Migrating to Changedatatypeforint (20140506103001)
== Changedatatypeforint: migrating ======================
-- change_column(:fds, :int, :integer)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PGError: ERROR: column "int" cannot be cast automatically to type integer
HINT: Specify a USING expression to perform the conversion.
: ALTER TABLE "fds" ALTER COLUMN "int" TYPE integer
my db files are listed below
20140506080404_add_int_to_fds.rb
class AddIntToFds < ActiveRecord::Migration
def change
add_column :fds, :int, :string
end
end
20140506103001_changedatatypeforint.rb
class Changedatatypeforint < ActiveRecord::Migration
def up
change_column :fds, :int, :integer
end
def down
change_column :fds, :int, :string
end
end
20140508105541_rechangedatatypeforint.rb
class Rechangedatatypeforint < ActiveRecord::Migration
def up
change_column :fds, :int, :float
end
def down
change_column :fds, :int, :integer
end
end
Sorry for my blunder.
Please give me the solution.
Thanks in advance.
Heroku uses PostgreSQL. In PostgreSQL int is a reserved word, you cannot use it as a column name.
Use something else for your int name
change_column :fds, :valid_name, :integer
SQL Key Words
If you want to cast from float to integer, one way to do it is:
class MigrationNameHere < ActiveRecord::Migration
def up
execute('ALTER TABLE fds ALTER COLUMN column_name TYPE integer USING round(column_name);')
end
end
This migration will convert all your float numbers to integer ones and it is not reversible so be careful. I advise you to have a backup before doing this.

Temporary index name too long in Rails migration

I've got a problem trying to rollback one of my migration. It seems as if Rails is generating a temporary table for the migration, with temporary indices. My actual index on this table is less than 64 characters, but whenever Rails tries to create a temporary index for it, it turns into a name longer than 64 characters, and throws an error.
Here's my simple migration:
class AddColumnNameToPrices < ActiveRecord::Migration
def self.up
add_column :prices, :column_name, :decimal
end
def self.down
remove_column :prices, :column_name
end
end
Here's the error I'm getting:
== AddColumnNameToPrices: reverting ============================================
-- remove_column(:prices, :column_name)
rake aborted!
An error has occurred, this and all later migrations canceled:
Index name 'temp_index_altered_prices_on_column_and_other_column_and_third_column' on table 'altered_prices' is too long; the limit is 64 characters
I've changed the column names, but the example is still there. I can just make my change in a second migration, but that still means I can't rollback migrations on this table. I can rename the index in a new migration, but that still locks me out of this single migration.
Does anyone have ideas on how to get around this problem?
It looks like your database schema actually has index called prices_on_column_and_other_column_and_third_column. You have probably defined the index in your previous play with migrations. But than just removed index definition from migrations.
If it is true you have 2 options:
The simplier one (works if you code is not in production). You can
recreate database from scratch using migrations (not from
db/schema.rb) by calling rake db:drop db:create db:migrate. Make sure that you do not create this index with long name in other migration files. If you do, add :name => 'short_index_name' options to add_index call to make rails generate shorter name for the index.
If you experience this problem on a production database it is a bit more complicated. You might need to manually drop the index from the database console.
Had this problem today and fixed it by changing the migration to include the dropping and adding of the index causing the long name issue. This way the alteration is not tracked while I am altering the column type (that is where the really long name is caused)
I added the following:
class FixBadColumnTypeInNotifications < ActiveRecord::Migration
def change
# replace string ID with integer so it is Postgres friendly
remove_index :notifications, ["notifiable_id","notifiable_type"]
change_column :notifications, :notifiable_id, :integer
# shortened index name
add_index "notifications", ["notifiable_id","notifiable_type"], :name => "notifs_on_poly_id_and_type"
end
end

How to handle failing migrations on reset because of deleted models/methods

An old one of my ruby on rails migrations contains both the actual migration but also an action to modify data:
class AddTypeFlagToGroup < ActiveRecord::Migration
def self.up
add_column :groups, :selection_type, :string
Group.reset_column_information
Group.transaction do
Group.all.each do |group|
group.selection_type = group.calculate_selection_type
group.save
end
end
end
def self.down
remove_column :groups, :selection_type
end
end
In this migration there are the usual add_column and remove_column migration statements. But there are also some model specific method calls.
I wrote this a couple of weeks ago. Since then, I have removed my Group model, which gives an error when I do a full migration with :reset.
rake db:migrate:reset
(in /Users/jesper/src/pet_project)
[...]
== AddTypeFlagToGroup: migrating =============================================
-- add_column(:groups, :selection_type, :string)
-> 0.0012s
rake aborted!
An error has occurred, this and all later migrations canceled:
uninitialized constant AddTypeFlagToGroup::Group
The thing is that in the current revision of my code, Group does not exist. How should I handle this "the rails way"??
I am thinking I could modify the migration by commenting out the Group.xxx stuff, but is this a wise way to go?
There is no value in leaving the group stuff in your migration now that it is gone from your project. I'd just edit the migration, drop everything from the db and migrate from scratch. There isn't even a reason to comment it out (you are using version control right?)
Also, I believe the "rails way" with migrations is spelled "Arrrrgh!"

Resources