I recently deployed a website to heroku and I am having problems with the database. I am using ruby on rails and when I first created my local databases I used SQLite. When deploying to heroku I had to change my databases to Postgres and in the process several migration files got removed and changed into a single migration. Now, when I run the postgres database on my localhost, I am still seeing all of the columns in my database, but when I visit the page on heroku one of the columns is missing.
I have checked both my local console and the heroku console and the databases are now different. The local console includes all of the columns in the database and the heroku console is missing one of the columns in the database, but is generating all of the other columns correctly. I have tried running a rake task on heroku and have pushed the most recent changes to heroku.
I tried to to add an additional migration to add the missing column to the database, but whenever I try to rake the migration it tells me that attribute already exists. Any help I can get is appreciated!
The best way to set up your database on heroku is with
rake db:schema:load
From the guides on migrations
Migrations, mighty as they may be, are not the authoritative source
for your database schema. That role falls to either db/schema.rb or an
SQL file which Active Record generates by examining the database. They
are not designed to be edited, they just represent the current state
of the database.
There is no need (and it is error prone) to deploy a new instance of
an app by replaying the entire migration history. It is much simpler
and faster to just load into the database a description of the current
schema.
I'm doing my first project on RoR I decided to use Devise gem for the authentication everything is working fine in Localhost, right now i'm able to sing_up, log_in, reset pass and some other default features that comes with devise.
What I don't understand is how everything gets setup once i push the project into production environment. Let me explain better.
-I see that devise generates db/schema.rb file based on the user.rb model that devise auto generate, these schema i assume needs to be created in the production db.
I have to push the project into git repo but..
1) How the code gets executed once is published
2) How the user table gets created
3) where do I need to specify the db connection (db, user, pass)
In general how is the process to migrate into production env?
I appreciate your help.
In rails db schema is controlled using migrations. Migrations are usually very small files living in db/migrations folder. Each of them defines a single subclass of ActiveRecord::Migration class.
Each migration is supposed to go both-ways, so it has to implement both up and down method (for rollback). In majority of the changes those are obvious (like when up action creates a table, down action should destroy it). For migrations like this you can use change function - rails will create down function automatically (assuming that all actions are reversible - some of the methods even accept extra arguments to make it possible like remove_column :table, :field, :integer. :integer bit might seem redundant here, however the action is irreversible without that information).
You run your migrations using db:migrate rake task. Effectively it will run all the migration which has not been run against current database. When it is done, it will dump your current database into db/schema.rb file. This file is used only as a snapshot of your current database schema, which is of great help if you need to get back to previous version of your application (which is why schema.rb should always be checked into your source control). It is also possible to recreate your database directly from that file rake db:schema:load, however it will cost you all your data.
If you check your database (any environment), you will notice there is one extra table called schema_migrations which does not appear in your schema file. This table contains all the migrations that has been executed against this database. This way rails will not retry migrations that already has been run.
There are many advantages of using migration system:
It is easy for every developer to bring their local database up to the latest schema.
It is easy to rollback your latest changes if deployment failed. (Not always the case)
So how to use it in production? You simply has to point the rake task to the right database:
RAILS_ENV=production rake db:migrate
You can find your database configuration in config/database.yml file. Note that this is the best practice not to store that file in source control and in case of production it is not advisable to store your database password there. Normally you will need to set it through environment variable.
It is important to remember couple of things about migrations:
Never, ever change the existing migration if there is a chance that someone has already run it. Especially, do not modify migrations that has run in production unless you are 100% sure what you are doing (for example fixing rollback). Since database remembers which migrations has run, it might lead to getting your local db out of sync with production db and hence lead to bugs.
Never ever change database schema manually - every change has to be made through migrations.
Well depending on where you're hosting your code you should still do a rake db:migrate to make the changes to the production DB.
If deployed on Heroku, run the following in the console:
heroku run rake db:migrate
Hope that answers your question?
I've been having a problem which doesn't seem uncommon (I've read a lot of stack overflow pages in the last 2 days) but every solution I've read hasn't worked for me.
I've been following this video tutorial
At 6:42 the tutor shows the tables in postgresql and mine don't show up.
When I try rake db:migrate the files migrate no problem. rake doesn't throw up any errors, the relevant .rb files are created in the models folder, my schema.rb looks right. It seems postgresql just isn't reading my schema file.
My problem sounds identical to
rake db:migrate doesn't seem to work in production
However typing rake db:migrate RAILS_ENV=production doesn't work. (I've tried this a few times after other rake commands like rake db:rollback STEP=3 in the past few days because I was paranoid it was the solution, this person on ruby forum, has the same problem and is offered the same answer).
This is my first attempt at programming anything and I'm loving the tutorial (and the learning curve this problem has turned out to be) Asking here is pretty much my last resort because I've tried everything I can understand online as a possible solution so please help me! Thanks a lot in advance
There is quite a bit of confusion going on here:
Migrations
Migrations are a convenient way to alter your database schema over
time in a consistent and easy way. They use a Ruby DSL so that you
don't have to write SQL by hand, allowing your schema and changes to
be database independent.
Postgres does not read your schema file or migrations - rather migrations run SQL queries against your database. In this case a CREATE TABLE ... query will be run when the migration is run.
Migrations are basically a more maintainable and sane way of doing what was classically done by opening a DB console and running SQL queries.
config/schema.rb is not actually used by the database or ActiveRecord - rather its created when you run migrations as a snapshot of what the database schema should look like. Its just a developer convenience. ActiveRecord gets its mappings by querying the database schema.
Migrations and generators
Migrations do not create model files either - those are generators such as:
rails g model Dude abides:boolean
Which creates a CreateDudes migration and a model at app/models/dude.rb.
In fact migrations are just concerned about altering the DB schema and don't care if the model file exists or not - the models is not actually used until you query the database for records.
ENV vars
RAILS_ENV=production sets a environmental variable.
rake db:migrate RAILS_ENV=test
Is the documented way to run a migration in a different environment. Some obscure shells require the ENV var to prefix the command.
However - if you are running a production server you should set the RAILS_ENV env var permanently - not on invocation! This prevents embarrassing misstakes when someone expected you to have configured the server properly and just ran rails s when restarting the server. See the documentation for your server OS on how to set env vars.
If you are still running the migration and do not see the expected results you most likely have not configured config/database.yml properly - the migrations are running. But not against the database you would expect.
http://guides.rubyonrails.org/active_record_migrations.html
I am getting an error for using a function provided by a special configuration on Heroku even though it works fine on my machine.
Specifically, I am using the Rolify method is_admin? on user, which is made possible by a configuration setting in an initializer file.
So far with Heroku I have migrated the database again, restarted the app and refreshed the page multiple times for each. How can I get Heroku to run the configuration file like my local machine does every time I reset the local server?
Error:
ActionView::Template::Error (undefined method `is_admin?' for #<User:0x0000000524c8e0>):
2012-07-22T09:00:53+00:00 app[web.1]: 1: <% if current_user.is_admin? %>
Code:
# config/initializers/rolify.rb
Rolify.configure do |config|
config.use_dynamic_shortcuts
end
Well, I tried one more thing and it worked, but here it is just in case.
I ran $ heroku run rake db:reset and it worked again. Not sure why, but oh well.
Edit:
The issue is that if you call Rolify custom methods when the role does not exist yet in the database, it results in an error. To get around this, either seed your database with all of the roles you'll need, or better, do not use dynamic methods.
For example, instead of:
#user.is_admin? use #user.has_role?(:admin) and it will not break.
I have two machines... a development machine and a production machine. When I first brought my rails app onto the production server, I had no problem. I simply imported schema.rb by running rake db:schema:load RAILS_ENV=production. All was well.
So, then on my development machine, I made some more changes and another migration, and then copy the new application over to the production machine. I then tried to update the database by running rake db:migrate RAILS_ENV=production. I get the following error:
"There is already an object named 'schema_migrations' in the database."
I'm thinking to myself, ya no kidding Rake... you created it! I ran trace on rake and it seems as if rake thinks it's the first time it's ever ran. However, by analyzing my 'schema_migrations' table on my development machine and my production machine you can see that there is a difference of one migration, namely the one that I want to migrate.
I have also tried to explicitly define the version number, but that doesn't work either.
Any ideas on how I can bring my production server up to date?
Update:
Let me start off by saying that I can't just 'drop' the database. It's a production server with a little over 100k records already in it. What happens if a similar problem occurs in the future? Am, I to just drop the table every time a database problem occurs? It might work this time, but it doesn't seem like a practical long term solution to every database problem. I doubt the problem I'm having now is unique to me.
It sounds like the 'schema_info' table and the 'schema_migrations' table are the same. In my setup, I only have 'schema_migrations'. As stated previously, the difference between the 'schema_migrations' table on the production server and the development machine is just one record. That is, the record containing the version number of the change I want to migrate.
From the book I read, 'Simply Rails 2', it states that when first moving to a production server, instead of running rake db:migrate, one should just run rake:db:schema:load.
If it matters, I'm using Rails version 2.1.
This is a guess, I admit: I think that because you first ran db:schema:load instead of db:migrate in your production environment, you got the structure of your db, but not the data that migrate populates into your schema_info table. So now, when you run migrate in the production environment, there is no data in schema_info which is why migrate believes that it hasn't run yet (because it hasn't).
That said... you say that you have looked in the "schema_migrations" table, and that there is a difference of one version from dev to production... I haven't heard of that table, although I'm a few months behind on my rails version. Maybe you could try creating a "schema_info" table in the production environment, with a single "version" column, and add a row with the version that you believe your production environment to be on.
If you get "There is already an object named 'schema_migrations' in the database." error message then I suspect that you are using MS SQLServer as your database? (As this seems like MS SQL Server error message)
If yes then which ActiveRecord database adapter you are using? (What is your database.yml file, what gems have you installed to access MS SQL Server database?)
Currently it seems that Rails does not find schema_migrations table in production schema and therefore tries to create it and this creation fails with database error message. Probably the reason is upper/lower case characters in schema_migrations table name - as far as I understand MS SQL Server identifiers are case sensitive.
Depending on the system used in production, I have seen instances where the below does not work:
rake db:migrate RAILS_ENV=production
But where this one does work:
RAILS_ENV=production rake db:migrate
Quirky, I know, but it's worth trying it to see if it makes a difference.
Regarding your update:
I don't understand what the difference is between your production schema_migrations and the dev version. Is there a record in both tables (there should be just 1 column, "version", right) or is there a single record in the dev DB and zero records in production? If there are zero records in the production table, then do this:
ActiveRecord::Base.connection.execute("INSERT schema_migrations (version) VALUES(#{my version number that production is supposedly on})")
Alternatively, you could try dropping the schema_migrations table totally on production:
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
Then, re-running rake db:migrate RAILS_ENV=production. That will run migrations from starting from version 1 though, which is probably not what you're after.
Alternatively alternatively, you could start an IRB session in your production environment, do either a "require" or "load" (I can never remember which, or if it matters) of the migration file that you want to load, and then call MyMigrationClass.up. You would need to manually set the version number in the schema_migrations table after that, as you would still have the problem going forward, but as a quick-fix type of hack, that would work.
I would just drop the DB, add it again and run rake rb:migrate. Brad is correct that when you ran the schema load, it didn't put any records in the schema_migrations table.
This is more complicated of course if there is data you can't lose on the production server. You could get the rake backup tasks (not sure if that is part of core or not) and then run rake db:backup:write on your production database, and then after you get the migrations up to date on production, run rake db:backup:read.
schema_info is from an old version of Rails. schema_migrations is the new kid on the block. You should be able to remove the schema_info table as it'll no longer be used. You'll probably want to search for any issues associated with this name change.
rake db:schema:load will load the database structure from schema.rb. This file is the current representation of the database structure. It's used when you have an empty schema (database) that needs all the tables and indexes creating. It saves you having to run all the migrations. If you have an existing production database with data in, you don't want to run it. As others have said that would be bad!
I know this post was some time ago, but I stumbled across it and it hasn't really been answered. As it comes up on google, here goes.
When you did a rake db:schema:dump (or when this was done for you by the build scripts) it will have put the definition of the migrations table into the schema.rb. At the end of the script, the process will try to create the table again, however it obviously exists already. Just remove the migrations table from the schema.rb before running rake:schema:load and there will be no error message.
You will need to set the version number in the migrations table to subsequently run migrations. So it is important to know what version your schema.rb relates too, or delete all the old migrations (they're safely in your SCM right?)
rake db:migrate RAILS_ENV=production
Use the db:schema:load task just for the first creation, incremental changes should be migrated.