I have 3 different schemas in one Rails application. My preparation of the test database using rake db:test:prepare fails with:
psql:/Users/me/myapp/db/structure.sql:7417: ERROR: relation "schema_migrations" does not exist
LINE 1: INSERT INTO schema_migrations (version) VALUES ('20131213203...
That's because it is not proper setting the Postgres search_path before doing all the insertions to the schema_migrations table. I haven't messed with this code in about 8 months and can't remember what I did. I haven't the faintest idea of how I even got those other schema to dump.
You may want to try rake db:structure:dump and / or rake db:schema:dump and try re-running rake db:test:prepare. The former should create the structure.sql and the later the schema.db
I was able to accomplish what I needed by doing two things:
Overriding the purge task under db:test in AR's railties to call a custom drop_database_objects method.
Using a little-known attribute in my database.yml: schema_search_path: public
The first thing lets me drop only the database objects I want, leaving my other support databases intact.
The second thing just creates the structure from my main database, and doesn't try to create the structure from the other databases. It looks like a bug in that it structure:dump doesn't set the schema search path appropriately at the end of the structure.sql script, right before the inserts into the schema_migrations table in a multi-schema instance. These fixes make that not necessary.
Related
My database is imported from open street map using a tool Osmosis. Every time I import new data using Osmosis it checks in the table "schema_info" and throws error if "schema_info" is not found.
Now on this same DB I made small modifications using rails migration. After I run rake db:migrate, rake automatically drops the "schema_info" table and replace it with "schema_migration".
Is it possible to tell rake to keep "schema_info" after migration?
You need to create the table in a migration, as you would for any table. Any modification to the database schema should come in the form of a migration, regardless of how minor.
Using Rails 3.2.18 and Postgres, I have a few tables for which I have created a view to minimize the data loaded by ActiveRecord. Everything appears to be running correctly when in the application, but when I try to run Rspec I get:
ActiveRecord::StatementInvalid:
PG::UndefinedTable: ERROR: relation "properties_view" does not exist
(where 'properties_view' is the view on the 'properties' table)
What can I do to ensure that Rspec loads views properly from Postgres?
Rails doesn't really understand "advanced" database concepts like views so they won't appear in your schema.rb. When rspec is setting up its test database, it will use schema.rb to create the database schema, since you won't find your views in schema.rb, you won't find your views in the test database that rspec will be using and everything falls apart.
The solution is to switch from schema.rb to structure.sql. You should be able to update your config/application.rb to say:
config.active_record.schema_format = :sql
and then do a rake db:structure:dump to generate the structure.sql file. Once you have that, remove schema.rb from your file system and revision control, add structure.sql, and try again.
If you don't want to switch to the SQL schema format, using the scenic gem may help (Scenic Gem Gitub).
They allow you to add SQL Views (also materialized) to migrations and also adds them to your ruby schema.
Worked for me like a charm.
I have a question regarding my migrations in rails.
Normally when i want to add a colum to a model for i dont make extra migrations but instead i perform this steps:
rake db:rollback
next i change the migration file in db/migrations and rerune:
rake db:migrate
The biggest problem is that when i do this i loose my data.
Previous i wrote migrations from the command line with for example
rake g migration Add_Column_House_to_Users house:string
The problem with this approach is that my db/migrations folder afterwards get very large and not very clear! I mean at the end i dont know wich variables the object has! Im not an expert in rails and would like to ask you how to keep the overview over the migrations!Thanks
Just a minor thought - I just use the file db/migrate/schema.rb to determine whats in the database as opposed to tracking through the migrations
You definitely shouldn't use db:rollback with a table with existing data.
I have a few production RonR apps with a ton of data and there are 100+ entries in the migrations table and adding new migrations to tweak tables is the rails way to do things. Not sure what you mean by lucid, but your schema and data model are going to change over time and that is ok and expected.
One tip. The migrations are great, but they are just the beginning, you can include complex logic as needed to fix your existing data (like so)
Changing data in existing table:
def up
add_column :rsvps, :column_name_id, :integer
update_data
end
def update_data
rsvps = Rsvp.where("other_column is not null")
rsvps.each do |rsvp|
invite = Blah.find(rsvp.example_id)
...
rsvp.save
end
end
Another tip: backup your production database often (should do this anyway), but use it to test all of your migrations before deploying. I run scripts like this all the time for local testing:
mysql -u root -ppassword
drop database mydatabase_dev;
create database mydatabase_dev;
use mydatabase_dev;
source /var/www/bak/mydatabase_backup_2013-10-04-16.28.06.sql
exit
rake db:migrate
I have an application that requires a sequence to be present in the database. I have a migration that does the following:
class CreateSequence < ActiveRecord::Migration
def self.up
execute "CREATE SEQUENCE sequence"
end
def self.down
execute "DROP SEQUENCE sequence"
end
end
This does not modify the schema.rb and thus breaks rake db:setup. How can I force the schema to include the sequence?
Note: The sequence exists after running rake db:migrate.
Rails Migrations because they aim toward a schema of tables and fields, instead of a complete database representation including stored procedures, functions, seed data.
When you run rake db:setup, this will create the db, load the schema and then load the seed data.
A few solutions for you to consider:
Choice 1: create your own rake task that does these migrations independent of the Rails Migration up/down. Rails Migrations are just normal classes, and you can make use of them however you like. For example:
rake db:create_sequence
Choice 2: run your specific migration after you load the schema like this:
rake db:setup
rake db:migrate:up VERSION=20080906120000
Choice 3: create your sequence as seed data, because it's essentially providing data (rather than altering the schema).
db/seeds.rb
Choice 4 and my personal preference: run the migrations up to a known good point, including your sequence, and save that blank database. Change rake db:setup to clone that blank database. This is a bit trickier and it sacrifices some capabilities - having all migrations be reversible, having migrations work on top of multiple database vendors, etc. In my experience these are fine tradeoffs. For example:
rake db:fresh #=> clones the blank database, which you store in version control
All the above suggestions are good. however, I think I found a better solution. basically in your development.rb put
config.active_record.schema_format = :sql
For more info see my answer to this issue -
rake test not copying development postgres db with sequences
Check out the pg_sequencer gem. It manages Pg sequences for you as you wish. The one flaw that I can see right now is that it doesn't play nicely with db/schema.rb -- Rails will generate a CREATE SEQUENCE for your tables with a serial field, and pg_sequencer will also generate a sequence itself. (Working to fix that.)
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