Attempted to Recreate Rails model, migrations messed up - ruby-on-rails

I had a rails Model List.
I typed rails d model list in my terminal, resulting in this:
invoke active_record
remove db/migrate/20140116161958_create__lists.rb
remove app/models/list.rb
invoke rspec
remove spec/models/list_spec.rb
Then I typed rails g model list name:string size:integer which gave me this:
invoke active_record
create db/migrate/20140213155321_create_lists.rb
create app/models/list.rb
invoke rspec
create spec/models/list_spec.rb
Now, running rake db:migrate gives me this:
== CreateLists: migrating ===============================================
-- create_table(:lists)
rake aborted!
An error has occurred, this and all later migrations canceled:
PG::DuplicateTable: ERROR: relation "lists" already exists
The issue is that my table was not deleted from my DB. I can't roll back the migration that created that table, because it was destroyed when i ran rails d model list.
I could create a new migration and drop the table, but it would be placed after my migration created when I ran rails g model list..., so I assume it would error too.
Is my only choice to delete the model again, create a migration to drop the table, then recreate the model?
Also, in the future, how should one go about deleting and recreating a model? Roll back the migration prior to rails d model?

1>
before running rails d model list
run
$ rake db:migrate:down VERSION=20140116161958
will roll back the list file to remove table lists from database.
2>
but since u have already destroyed your model what u can do is delete table lists from rails database console. try this
$ rails dbconsole # from your app root path
and then type drop table lists;
3>
you can drop your table from rails console also
$rails console
Then just type:
ActiveRecord::Migration.drop_table(:lists)
4>
also u can create a migration file to drop your table :
$ rails generate migration DropListsTable
this will create an empty migration file now edit that file to look like:
class DropListsTable < ActiveRecord::Migration
def up
drop_table :lists
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
then run $ rake db:migrate

Related

Rails: Rollback Mistake

I have created a table called "property" and I did not migrate it yet. I then wanted to delete the table, so when I did rake db:rollback as below. My previously created table, which I did not want to delete at all, is now reverted. How should I revive my model "comment" and instead delete the last model "property" only.
Some comments say do "redo" or "run migrate" but if I do a rake db:migrate, I feel like it will delete the comment model permanently. Am I wrong? What is right solution to bring back my comment model?
:~/workspace (revoke) $ rails g model property title address note price$ priceW
Running via Spring preloader in process 3066
invoke active_record
create db/migrate/20160517222114_create_properties.rb
create app/models/property.rb
invoke test_unit
create test/models/property_test.rb
create test/fixtures/properties.yml
:~/workspace (revoke) $ bundle exec rake db:rollback
== 20160506122941 CreateComments: reverting ===================================
-- drop_table(:comments)
-> 0.0011s
== 20160506122941 CreateComments: reverted (0.0096s) ==========================
Once you've done the rake db:rollback, you've made a change to the database. In this case, it dropped your comments table, as you can see in the output: drop_table(:comments). The data is gone, already. We've all been there at least once.
Running rake db:migrate will restore the comments table structure, but not the data in it. In this situation, if you want to get to the point that your new table property isn't migrated, you can run rake db:migrate to run all new migrations, and then rake db:rollback once to rollback the migration for property.

manually adding an integer field to rails scaffold

I'm new to rails...I made a scaffold "Reviews" but want to add another field "ratings", as an integer. I did the following:
added t.integer :ratings in the migration file..ran rake db:migrate
in spec folder: added it in views/app/ edit, index, new, show
in app/views/app added it in the json files
in app/controllers/app added it in the review_params function
still however whenever I try to reference (by showing a Review) it I get
undefined method `ratings' for #
There must be something else I need to add somewhere to have it be part of my Reviews scaffold. I've been trying to figure it out for 5 hours but still have not. When I try to remake a scaffold and run rake db:migrate I get an error saying that the databases already exist so I would like to just manually add it to my existing one if possible, I just can't seem to figure out how even though I've already done it once for a string.
Any help is appreciated thank you.
To add an integer field to a model you can do something like this.
rails generate migration AddRatingToReviews rating:integer
This should handle everything for you by generating a new migration file like so.
class AddRatingsToReviews < ActiveRecord::Migration
def change
add_column :reviews, :rating
end
end
Then you can run rake db:migrate to add the column to your review model.
NOTE: Before doing all of this, please delete all your manual changes. If necessary use rake db:rollback which will rollback your most recent rake db:migrate.
Recommendation
If you are new to rails and don't understand MVC, I suggest not using scaffolding because you'll have a tough time knowing what it is doing. Go through this awesome tutorial by Michael Hartl to really learn rails quickly. http://ruby.railstutorial.org/
*Awesome gem *
Use the annotate gem to display the attributes contained within your model directly in your name_of_model.rb files.
https://github.com/ctran/annotate_models
rails generate migration AddRatingsToReviews ratings:integer
Then
rake db:migrate
If you have not done any major changes in your generated scaffold.
Simplest way to get the ratings across views would be as below:
Rollback the changes that you have migrated
rake db:rollback VERSION=version_number
Where replace version_number with the version_number prefixed on your migration file.
For eg: If your migration filename is 20140314190622_create_reviews.rb then command should be
rake db:rollback VERSION=20140314190622
Destroy the scaffold of Review
rails d scaffold Review
After this generate the scaffold again with the integer field
rails g scaffold Review ratings:integer .... ## Add other field in place of ....

Rails destroy model not deleting migration

I originally had a migration called CreateUsers that had a table already.
Due to my stupidity, i thought i had to do a rails generate migration in order to add indexes to the table. When i did a migration it was this:
rails generate migration CreateUsers years:integer
So it creates a migration with the timestamp and so on, and i tried deleting using this
rails d migration migration_filename
Its giving me some error regarding this
/Users/giowong/.rvm/gems/ruby-2.0.0-p353/gems/activerecord-4.0.2/lib/rails/generators/active_record/migration/migration_generator.rb:57:in `validate_file_name!': Illegal name for migration file: 20140219230444_create_create_users.rb (ActiveRecord::IllegalMigrationNameError)
In the schema.rb table stll exists
should i manually delete both?
You don't want to run rails d against the filename, but against the migration name you had in your generate.
Try: rails d migration CreateUsers
In order to drop the table, you'll want to rollback your migration as well:
rake db:rollback STEP=1
STEP=1 assumes this was the last migration run. You also may need to prepend bundle exec if you're using bundler in your app.

Rails: how to rollback a botched migration

I'm an idiot...screwed up a migration in Rails:
thinking migrations would work like model generators (using references:modelname) I did the following:
$ rails g migration add_event_to_photos references:event
which created the migration
class AddEventToPhotos < ActiveRecord::Migration
def change
add_column :photos, :references, :event
end
end
And now my development database (SQLite3) has a references column of type event in the photos table.
And my schema.rb has a line in the middle saying:
# Could not dump table "photos" because of following StandardError
# Unknown type 'event' for column 'references'
rake db:rollback is powerless against this:
$ rake db:rollback
== AddEventToPhotos: reverting ===============================================
-- remove_column("photos", :references)
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `to_sym' for nil:NilClass
So, how to roll back and maintain my development data in the database? I'd even be happy trashing the photos table if that's my only choice..but don't want to have to rebuild the whole thing. What to do?
btw- for anyone reading this about to make same stupid mistake...don't! Use the correct migration generator:
$ rails g migration add_event_to_photos event_id:integer
The easiest way I found to do this was to recreate the table in the schema.rb file in /db/. Afterwards I ran a rake db:reset (if it says you have pending migrations, just delete them and try again).
This took care of the problem.
Go into the database by ./script/rails dbconsole. Then type these commands:
.output dump.sql
.dump
In the file dump.sql you will have the SQL commands used to recreate and populate your database. Just edit it with your favourite editor (like vim ;-) removing or fixing the column type. You may also remove the invalid migration identifier from the schema_migrations table. Drop your database (I suggest just rename the db/development.sqlite file), create new database and read the dump file into it (using command .read dump.sql).
Now you just need to fix and run your migrations.
add an empty down method and run rake db:rollback
edit ahh that's the new migration syntax, you can replace the body with simply:
def self.down; end
which is the old syntax, or perhaps delete the body altogether (haven't tried this) and then run rake db:rollback
Just an idea, I know it's not SQLite specific you can revert to an older version schema perhaps, load it up. And try again from there? You can revert (checkout) specific files in GIT. And then do def self.down; end, as was suggested by another poster.
The problem arises because while SQLite will create the schema with whatever type you give it (in this case event it can't dump that type back to ActiveRecord.
You need to edit the sqlite_master file and change create table string (sql) to be the right thing.
You probably want to back up your table first since messing up that string will wreck your table if you do it wrong.
Here is a related rails issue

How do I add a new element to an existing class?

I already generated a class by "script/generate model blah blah1:string"
How would I add a "blah2:string" to the existing model? Is there a script or do I have to manually edit the database and every file?
Create migration:
./script/generate migration AddBlah2ToBlah blah2:string
This will create migration in db/migrate ruby file with migration - you can check if it correctly added column to table. Then run:
rake db:migrate
or in production environment:
rake db:migrate RAILS_ENV=production
This will add column to your database and you can use it in Rails:
#blah = Blah.first
#blah.blah2 = "new string"
...
You can create new migration of change table.. Check this.. See section 3.2

Resources