I currently have a migration and I simply want to add a couple more values to this migration such as to_limit and from_limit along with their default values (5&10). How should i do this?
class AddUserToCompany < ActiveRecord::Migration
def change
add_column :companies, :user, :jsonb, default: {"to_dist"=>50, "from_dist"=>70, "trs_one"=>100, "trs_two"=>120}
end
end
I added some changes which also requires "to_limit"=>5 and "from_limit"=>10. Please suggest on how to add a new migrate file and add the changes.
Rails version - 4.2.11
This is my first time working with a rails application. So i am really confused on how to proceed with this.
1.If this changes are in progress (not already used by other) then you can rollback this migration by command
rollback last migration
rake db:rollback STEP=1
In order to rollback ONLY ONE specific migration
rake db:migrate:down VERSION=20220905201547
and after applying changes, run rake db:migrate
If migration was created earlier then you can create new migration to apply your changes
generate new migration by command
rails generate migration nameOfMigration
I hope this helps
Related
Good morning everyone,
I am trying to complete the calender app from Codeacademy, and I need to complete the following steps.
Open the migration file in db/migrate/ for the days table, and add the following columns:
a datetime column called date
Open the migration file in db/migrate/ for the days table, and add the following columns:
a datetime column called date
Open the migration file in db/migrate/ for events tracks table, and add the following columns:
a string column called name
a datetime column called from
a datetime column called to
a string column called location
a references column to the Day model
So far, I have added it manually to the migration files like so:
class CreateDays < ActiveRecord::Migration
def change
create_table :days do |t|
t.datetime :date
t.timestamps
end
end
end
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string :name
t.datetime :from
t.datetime :to
t.string :location
t.timestamps
#Not sure how to add references column????
end
end
end
However, I am running into an error when I run rake db:migrate, I get no output. Is there supposed to be an output? I have run rake db:migrate --trace and here is the output:
A migration file is like a script which changes your database in some way. It does not store the state of your database.
It will not do anything unless you run it: your database has a special table to keep track of which ones have been run already, called schema_migrations. When you do rake db:migrate you run all scripts in that folder which haven't been run already, according to that table.
So, if you run a script, then change it, then do db:migrate, it won't run it again because it thinks it's been run already. If it did run it again, it would likely blow up because it would be trying to add lots of columns that already exist.
If you define a table in a migration, then later want to add more columns, you can either roll the migration back (which will drop the table), then run it again with the added columns, or write a new migration which just adds the required new columns. The latter approach is usually best.
Whenever you run rake db:migrate,it runs all the pending migrations using the timestamp which every migration file has ..such as YYYYMMDDHHMMSS_create_products.rb.
Any file which has a migrations greater than the previously run migration timestamp will be picked up during rake db:migrate and then checked whether the changes are present in the db.
For example :
For a migration file 20080906120001_add_details_to_products.rb...if you have ran it then all the changes will be added in the db.if you edit it and then run it again then it won't be picked up as timestamp of migration should be grater then previously ran file,which is not.
You can manually change the migrations by editing few numbers so that it gets picked up again without creating a new file.
I would recommend create a new one as they are way to maintain and are each migration should be unique.
I assume that you have ran the migrations before. So there is a table named schema_migrations where it stores the migration which has already ran so you cannot re run them. The best way to add new columns to an existing table is to create a new migration like this:
rails g migration add_some_columns_to_events name:string
and name the other columns. And still if you need to do it using the existing migration then what you can do is:
rake db:migrate:down VERSION=<version_of_migration>
and then add up the columns in migration file and run:
rake db:migrate:up VERSION=<version_of_migration>
You can also rollback your last migration and re run the migration using:
rake db:rollback
Hope this helps.
You can only run a migration once - if you've already run the migration, you have two options:
You can roll back the migration with rake db:rollback, edit it, and then run it again with rake db:migrate, or
You can generate a new migration and put your changes in it. Then you can run the new migration with rake db:migrate.
So I've been going through a lot of rails tutorial, and I get that the default for adding a new column to a database is , for example,
rails generate migration add_reset_to_users reset_digest:string reset_sent_at:datetime
The above will add a reset_digest in the form of a string and reset_sent_at in the form of a date to the migration add_reset_to_users
My questions is what if I am clumsy one night at 4 AM and only call the following
rails generate migration add_reset_to_users reset_digest:string
I completely forgot about reset_sent_at but want to implement it the next morning. I made the mistake of adding the link directly to the db file, which was a huge mistake.
In this case what should I do? Do I simply call a new migration such as
rails generate migration add_reset_sent_to_users reset_sent_at:datetime
or is there an even better way?
first, if you have not run your migration, you can directly open the migration file, and add your column to the file, as
def change
add columns :table_name :column_name :column_type
end
In your case, you will modify the file as,
def change
add columns :users :reset_digest :string
add columns :users :reset_sent_at :datetime
end
and then run
rake db:migrate
if you have already ran your migration, and you have not run any other migration after that, you can undo it, by
rake db:rollback STEP=1
and then edit the migration file, and run your migration
Rule of thumb for migrations in Rails is that you always create a new migration file unless you have not already shared your code with others, i.e. pushed to remote repository, otherwise you can just change the old migration after running $ rake db:rollback and everything will be fine, and nobody will know about it, and won't affect other developers work(since it's still on your local repository).
So, I'd encourage you to create a new migration if you have already committed and pushed the code onto remote repository, and changing the old migration file again will hurt other developers productivity. In case of any confusion, always create a new migration:
rails generate migration add_reset_sent_to_users reset_sent_at:datetime
I think it depends what state your rails app is in.
If you were working on a production app then editing migrations is not advisable due to data loss and changes should be made with a new migration.
If your working locally in development then I would edit the migration directly and add the missing column and rerun your migration.
Don't be worried about editing you migrations, just remember to rake db:rollback the migration you are editing before making changes or you will encounter errors.
This is where changing your migration from:
def change
add_column('users', 'reset_digest', :string)
add_column('users', 'reset_sent_at', :datetime) # Would have to perform rollback before adding this line
end
to:
def up
add_column('users', 'reset_digest', :string)
add_column('users', 'reset_sent_at', :datetime) # Added after migration
**rake db:migrate
end
def down
remove_column('users', 'reset_digest', :string)
remove_column('users', 'reset_sent_at', :datetime) # Add this after rollback
**rake db:rollback
end
Allows you to make changes to your migrations before you rake db:rollback
This requires a bit more code but I find it easier when I'm building a new app and things are changing frequently.
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 ....
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.
Here's my story: I had something like this set up a while ago.
create_table(:users) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
t.integer :total_pageviews
and "total_pageviews" worked fine. I could set it to zero, increment it, multiply it, call it, whatever. but let's say i want to add:
t.integer :total_votes
What do I have to do to configure total_votes as an attribute? Whenever I try to use "total_votes", I get undefined method error. I'm thinking that the answer is something like rake db:migrate or similar.
You should not ever alter existing migrations. If you have checked them in to your version control system and somebody else runs them and then you add a new field to them and commit that change, they will not know to get that change. Then you must tell them and it's a pain in the butt to fix.
If you've not committed it yet then rollback the migration (rake db:rollback), make the necessary modification and re-run it again (rake db:migrate).
But in the Real World, you would create a new migration which adds this field using rails g migration add_total_votes_to_users total_votes:integer.
Rails will interpret this migration name and know what to do with it, generating a migration that contains this line:
add_column :users, :total_votes, :integer
Then when you run this migration it will add this total_votes field to the users table which will make an attribute of the same name for all User objects.
Are you adding this after the migration has been run? So, the users table exists and you want to add a column to it? If so, you need go create a migration like
rails generate migration add_total_votes_to_users
Open it up (just to verify that the table and column are correct). Then run the migration.
If you app is in production, then you should create a new migration. If you app is in pre-production stage, and you have a small development team with good communication, then I recommend you to go ahead and modify the migration and then do
rake db:drop
rake db:create
rake db:migrate
then you can commit the modified migration file and let the rest of you team know that that you have changed a migration file.