Can Rails schema table be outside the database? - ruby-on-rails

We have a legacy PostgreSQL database that is perfectly accessible from a Rails app except that when the vendor provides an update one of the consistency checks they perform against the database fails because Rails has built a "new" table there, the schema migrations table. Is it possible to direct creation of this table elsewhere? Or is it possible to use the schema cache in Rails 4 to effect this? The release notes section 3.3 on General things says "Schema cache dump (commit) - To improve Rails boot time, instead of loading the schema directly from the database, load the schema from a dump file."

I found an old blog post about this last time I tried it here. Copying the relevant parts:
To make a dump of your schema, execute the following rake task:
RAILS_ENV=production bundle exec rake db:schema:cache:dump
This will generate a file db/schema_cache.dump, that Rails will use to load the internal state of the SchemaCache instance.
To disable the schema cache dump, add the following to your config/production.rb file:
config.active_record.use_schema_cache_dump = false
If you would like to clear the schema cache, execute:
RAILS_ENV=production bundle exec rake db:schema:cache:clear

Related

Ruby on Rails. Why schema.rb builded on existing data through db:schema:dump is almost empty?

I am trying to find the correct (any) method to create an application in Ruby on Rails having an existing database (PostgreSQL) with data and fresh app made with:
rails new --database=postgresql -J --skip-coffee .
I found https://github.com/frenesim/schema_to_scaffold but first I need to have a file with a database structure: schema.rb. I’m looking for a way to do it automatically.
In result of rake db:schema:dumpfile schema.rb is generated, but only with content like that:
ActiveRecord::Schema.define(version: 0) do
enable_extension "plpgsql"
end
And I stuck here. Why that file is empty? Why are there no tables here?
I have a connection with DB and no errors. I did rake db:create before to test. Creation of bases described in database.yml is successful.
At the beginning I used Docker containers and this is my goal. But to exclude the probability of error, I installed the environment in the system (macOS Mojave) based on the socket. And I’ve got the same effect.
How to generate schema.rb with structure of existing database? Or is there different way to build RoR app based on the existing data structure?
Update: Connection with the new database I only did for testing purposes. To verify configuration.
Here's what else I did:
Dump existing structure with
pg_dump --schema-only app_development > db/structure.sql
I changed name in database.yml to have fresh place to import.
rake db:setup created new DB
rake db:structure:load create tables from db/structure.sql file in DB correctly.
But rake db:schema:dump still generate empty file as earlier.
If you have set proper db config you can use rake db:migrate to regenerate the schema file.
edit:
Ok so lets check if I understood correctly:
you have an existing db with tables and data in it
you have brand new rails app
you want to reflect db structure in you schema.rb file
Is that correct? If yes then like I wrote before - without adding any new migrations to your codebase, run rake db:migrate. That task not only applies changes from the migration file but also updates your schema file to be in sync with the actual database.
I've got it! Two days of my life.
File used to import PostgreSQL database has at the beginning:
CREATE SCHEMA employees;
-- and later
CREATE TABLE employees.department;
I thought that since Rails generates database by rake db:structure:load , the file's syntax is correct.
But when I create manually table users in new empty database and then pg_dump that new base I don't have CREATE SCHEMA query there.
And finally rake db:schema:dump fills schema.rb with tables as I want:
create_table "users", id: :serial, force: :cascade do |t|
t.text "name"
end
Because that fresh pg_dumped file has CREATE TABLE public.users query. public.
I think the key is in comments in database.yml file:
# Schema search path. The server defaults to $user,public
#schema_search_path: myapp,sharedapp,public
One picture is more valuable than a thousand words: that's the differences Table users on the right goes to schema.rb after rake db:schema:dump
Thanks guys for the comments. It's made sure me that I do not make a terrible mistake.
It sounds like you did rake db:create which creates a new database for you and then did rake db:schema:dump which generated a schema.rb file for you from the newly created (empty) database.
If you have an existing database that you want to use you will need to modify your database.yml file to connect to it.
If you want to create a new database you will need to generate Active Record database migrations e.g.) rails generate migration CreateProducts name:string part_number:string and then run them rake db:migrate to update your database and generate your schema.rb.

Rails4: production environment create database not using many migrations

I am deploying a rails app to nginx.
There are many migrations in the development stage.
How to create the production schema in a simple way instead of reading many migration.rb files ?
Because I deleted several migration files during develepment. Now when deploy production environment it shows me some errors
Thanks
You can use the schema.rb file (via rake db:schema:load), but beware it will drop all existing tables. If you have existing data you will lose it.
Once you load the schema then it sets the database version, so only new migrations that are created after the schema file was created will run in the future.
Here is some info for Rails 4.2 about schema dumping:
Schema Dumping and You

How to create database from schema.rb without initializing Rails?

I am trying to create all my tables from schema.rb
I used the command: "rake db:schema:load"
However, this fails because in one of my initializers, it is referencing a model/table that obviously doesn't exist (since the database is empty)
I could comment out these lines, and then run schema:load again, but is there an alternative?
Probably the fastest way is to just move the offending initializer to a temporary directory that is outside of the app, and then run your schema load. But if that doesn't work, or isn't an option for some reason, you could always work around that by creating a bare bones rails app to do the schema load:
Create a new rails app: rails new (app)-fixer
Copy your gemfile (unless there are specific exceptions) to the fixer app.
Copy your database.yml config to the fixer app.
Copy your schema.rb file to the fixer app.
Do all appropriate "bundle install" commands as needed for your app.
Then run "rake db:drop db:create db:schema:load"
That will build up a new database from scratch, based on your current schema.
You can add a check for the table existance in your initializer.
if TheModel.table_exists?
// do something with the model
end

What is the best practice for adding records to a production DB once deployed to a VPS?

I just deployed my rails app to a Linode VPS, and was wondering what would be the best way of adding records to the DB.
I have tables such as Categories, which I'd like to populate.
I thought of the Taps gem, using a csv, or an sql dump file.
I'd like to know if there are any tools out there for this?
Thanks
For this puporse there are the so called seed file which is default in:
db/seeds.rb
You can add entries here ( there is an example in the seed file ), which you can generate after deployment with a rake task:
rake db:seed
You probably are using bundler as well, so use:
bundle exec rake db:seed
In case of large number of seeds you can always create multiple files, see this blogpost about handling large seed files.
However, if you are in a state, where the already existing data in the app is crucial and you are changing servers or database drivers you wanna take a look on yaml_db gem which gives a nice method to abstract the existing data away from your actual db driver and export it into a .yaml file which you can import later back e.g.: after deploying on a new server.
See Railscast - #179 about seeding.
The rails way would be to use seed data in db/seeds.rb and then populate it by using rake db:seed.
You could also use a sql dump file and restore by issueing mysql -u <user> -p <database_name> < <mysql_dump_file>
The Easy Reference Data gem is similar to db:seed, but will update records if entries already exist. It also has easy integration with Capistrano.
Full disclosure: The company I work for developed the gem.

Is it possible to run a SQL-only file from a "rake db:create"?

I'm trying to install a software called Teambox in my Dreamhost shared account, following these instructions.
I have no experience with Rails. I just want to install the software in the shared hosting.
In this shared hosting, all dependencies are ok, but I have to create the dabatase from their panel. I can't create in command line (ssh).
So, when I run "rake db:create" these's an error, because the db already exists (because I created in panel).
I've already contacted support. They can't change this policy.
How do I populate my tables "by hand" in this case? Which files should I look inside Teambox's folder...
Thanks!
rake db:create should create your database and that's all. It doesn't creates your tables.
There are several rake tasks to do that :
rake db:migrate which will execute your migrations. So create all your tables.
rake db:seed which will add the original data of your application. See Database Seeding
You don't need to be able to create the database to do any of these.

Resources