This is my first Stackoverflow post, so please let me know if I can specify my problem any better than I am: I've searched the site and haven't found anything that fixed my problem.
I have an app running locally with an Event model.
The model has a start_date column and I later added an end_date with a migration.
Everything works locally.
When I deploy it to Heroku I get an 500-error when trying to create an Event entry.
It first gave me an ActiveRecord::MultiparameterAssignmentErrors, saying that it couldn't assign anything to end_date=.
I looked through everything and made sure that it was a permitted parameter.
Then I looked through my migrations and found to my surprise that my AddEndDateToEvents migration didn't exist, but the end_date column is in my schema model.
So I ran a rails g migration AddEndDateToEvents where I wrote:
class AddEndDateToEvents < ActiveRecord::Migration[5.2]
def change
remove_column :events, :end_date
add_column :events, :end_date, :date
end
end
I ran rails db:migrate and everything works locally.
Now when I push it to Heroke and I run db:migrate there as well, it of course terminates and tells me that it cannot remove the column end_date because it doesn't exist in the model.
I'm stuck. What shall I do? :(
References of my source code
GitHub: https://github.com/Curting/mydanceplan
Heroku: https://mydanceplan.herokuapp.com/
Thank you in advance!
Oliver
I solved it with your help, Mark! :-)
I did the following:
1) Roll back migrations
I ran rails db:migrate:status and saw that I should roll back two migrations to get completely clean of my attempts to add/remove the end_date column.
When I tried to rollback, it gave me an error that my remove column migrations weren't reversible. I had to enter the type of column. So I added that as a third parameter. Example: remove_column :events, :end_date, :date
After that a rollback was possible. The easiest way was to run rails db:rollback STEP=2.
2) Delete down migrations and check schema
After rolling back my migrations, I deleted the unneeded migration-files from the folder. Also, I checked my schema file and manually removed the end_date row from the model.
3) Create conditional remove row migration
Using Mark's answer, I added a new migration with the following code:
class AddEndDateToEvents < ActiveRecord::Migration[5.2]
def change
remove_column(:events, :end_date) if column_exists?(:events, :end_date)
add_column :events, :end_date, :date
end
end
4) Reset database and run db:migrate
I then did my git push && git push heroku and then I ran heroku restart && heroku pg:reset DATABASE --confirm APP-NAME && heroku run rake db:migrate, where APP-NAME was the name of my app.
And now it works! :-)
Thank you very much. I'm quite blown away by the quick and helpful response, and the fact that some person out there on the interwebs took the time to edit my post and format it nicely.
Generous community. Nice!
Looks like your migrations are out of sync as you say. The best way to cover both bases is to add a conditional into the migration. Rails comes with a method called column_exists?
https://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/column_exists%3F
Which we can use in our migration:
class AddEndDateToEvents < ActiveRecord::Migration[5.2]
def change
remove_column(:events, :end_date) if column_exists?(:events, :end_date)
add_column :events, :end_date, :date
end
end
That should now work whether or not the initial migration has been run
EDIT: It probably is best to keep both your databases in sync, so if your Heroku DB has no important data in it, you can always simply drop it, recreate it and run all migrations from the start. I think that's preferable if you can afford to lose whatever data is in your Heroku DB
Related
I have created 2 tables (categories and products) and I did has_many association like Category has_many :products and Product belongs_to :category.
When I do a migration like:
rails generate migration add_product_id_to_categories product_id:integer
then migration is running but not seeing product_id in Category.
I've tried multiple ways like
add_product_id_to_category product_id:integer
but still facing the same problem.
You only generated a migration file (rails generate migration add_product_id_to_categories product_id:integer). You have to run the migration with rake db:migrate.
Generating a migration is a different thing than actually running it. You just generated it, and in order to execute what you have written, you need to run it, and you can do so by invoking the following command:
rake db:migrate
Not sure that either you have run the migration or not, run the following command, and it will tell you the statues of all the migrations. If the status is up, the migration has been run, and for down, a migration couldn't be run.
rake db:migrate:status
When you run a migration, and you would like to get notified in terminal that it has been successfully run, you can add a puts statement in there like following:
class AddColumnToCategories < ActiveRecord::Migration
def change
add_column :categories, :product_id, :integer, index: true
puts "product_id column has been added into categories."
end
end
Have you tried rails generate migration AddProductIdToCategories product_id:integer?
When you have created the migration if you look inside the migration file you can see if any code has been generated in the change method before you run the migration. If it has not generated any content you can manually add it:
def change
add_column :categories, :product_id, :integer
end
I have the following migrations
Problem is that rake db:migrate is not executing the first migration and no users table is created.
What could be the reason for this?
What could be the reason for this?
Main reason is probably that you've already ran the migration - or perhaps later migrations - and Rails therefore does not think it needs to run it.
A good way to see if this is the case is to open your db/schema.rb file:
You'll see the latest migration your schema is running. If this supersedes the one you're trying to invoke, it will not run.
--
Fixes
You could generate a new migration, and copy the code over:
$ rails g migration AddUsers2
You'd then add the following:
#db/migrate/_____.rb
class AddUsers2 < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
Alternatively, you could wipe your DB and start again. This can be achieved using rake schema:load. THIS WILL WIPE ALL DATA AND START AGAIN
I need to add some columns to a table in my schema. Can someone tell me the best way to do this?
The following seems incomplete or wrong since the schema.rb file did not update to include the new column and all of the corresponding view files (edit,index,new,show) did not update to include the new column. Not to mention the bloat of all of those migration classes that get generated. Thanks
ruby script/generate migration RecordLabelToAlbums record_label:string
exists db/migrate
create db/migrate/20121130125859_record_label_to_albums.rb
Creates this:
class RecordLabelToAlbums < ActiveRecord::Migration
def self.up
end
def self.down
end
end
I then added this:
class RecordLabelToAlbums < ActiveRecord::Migration
def self.up
add_column :albums, :record_label, :text
end
def self.down
remove_column :albums, :record_label
end
end
The I ran:
rake db:migrate
Got This:
Mysql::Error: Table 'albums' already exists: CREATE TABLE albums (id int(11) DEFAULT NULL auto_increment PRIMARY KEY, created_at datetime, updated_at datetime)
The code you added is correct.
The error suggests that for some reason your system appears to think it has not yet run the original migration that created the albums table. The state of migrations (in Rails 2) is specified in a table in the database called schema_migrations -- if this gets confused then it will try to re-run migrations. I am not sure what might cause it to get confused, but I do recall this happened a couple times back in 2008 when I was using Rails 2.x.
The table is simple -- you can see what's in it from a SQL prompt -- just the names of migrations it thinks it has run, I think.
If you don't mind losing some data, you can try rake db:rollback or even rake db:reset to get back to the beginning. rake db:rollback STEP=2 will rollback the last 2 migrations.
If you need the data, correct the contents of the table by adding one or more new records referencing the migrations in app/db/migrations that may have been missed. The order is important, I think (the format changed a little in Rails 3, I don't recall how).
Any time you want to add or change the database schema, use rails to generate a migration, and then run rake db:migrate once it's ready to go.
And just asking: is there any way you can move to Rails 3. It's been out for years now, and Rails 4 is coming soon. You'll find yourself in a backwater of incompatibilities, deprecations, security and performance issues and so on if you don't take the hit and upgrade.
How do you add a column to a table using ActiveRecord through the terminal. I am trying to use add_column method but its not working. Any ideas please?
It is better to write a migration and a must if you are working with a team. When you make db changes, then every developer's environment has to be updated also. Otherwise, you will have some mad developers at you.
rails generate migration AddPartNumberToProducts part_number:string
will generate
class AddPartNumberToProducts < ActiveRecord::Migration
def change
add_column :products, :part_number, :string
end
end
Then you run the migration
rake db:migrate
http://guides.rubyonrails.org/migrations.html
Edit:
For a rails console command line check #tadman's answer or use what Bengala proposed like
ActiveRecord::Migration.add_column :products, :part_number, :string
You can run migrations directly in rails console rails c with ActiveRecord::Migration
For your purpose the next command will do what you ask:
> ActiveRecord::Migration.add_column :table_name, :field_name, :field_type
If you're just hacking around, it's usually easier to manipulate the database using a SQLite client of some sorts than through the Rails DB layer.
If you're doing this for a project, create a proper migration file and run it.
If you're determined to do this, the add_column method is available through the ActiveRecord::Base.connection driver object.
I have a series of migrations for refactoring on the upcoming release. Some of the migrations are used to move columns around.
When I run the migrations all at once, the specific column in the following example is never copied to the new place.
def up
add_column :buy_topics, :price, :integer
say_with_time 'Move price and value to buy/topics' do
bar = ProgressBar.new(Buy::Topic.count)
Buy::Topic.includes{topic}.find_each do |topic|
topic.price = topic.topic.price
topic.save
bar.increment!
end
end
remove_column :topics, :price
end
Even though the values are not copied, the columns were still created and removed successfully though.
However if I run all the migration up to the the one prior to this (e.g. rake db:migrate VERSION=XXXXXXXXn-1), and then manually run this one particular migration (rake db:migrate VERSION=XXXXXXXXn), the values are copied across.
So in summary, if I run that migration individually it works, otherwise it will not work
What could be the reason behind this?
Try doing this:
Buy::Topic.reset_column_information
For more information, look at "Using a model after changing its table" on [this page][http://api.rubyonrails.org/classes/ActiveRecord/Migration.html].