I'm following this tutorial,
and I'm having a problem when running rake db:migrate
In db/migrate I have the create_post.rb file:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :text
t.timestamps
end
end
end
But it does not create the table.
My database.yml file is:
development:
adapter: mysql2
encoding: utf8
database: blog_development
pool: 5
username: root
password:
socket: /tmp/mysql.sock
The output from rake db:migrate seems ok.
I'm using phpMyAdmin to handle the database, which is correctly created manually by me.
What am I doing wrong?
If you are connecting to the right database everything seems fine to me.. I had a similar problem a few weeks ago and the accepted answer of this question fixed my issue.
Here are the steps to run:
rake db:drop:all
rake db:create:all
rake db:migrate
I hope it will fix your problem.
WARNING: this will erase your database.
Could you please tell which OS you got?
Delete the line:
socket: /tmp/mysql.sock
and run:
db:migrate
Give the output of:
db:migrate:status
If this is not working for you, you could also try to add:
host: 127.0.0.1
to your database.yml file
If nothing stated above works please do check your schema.rb for migration contents. If migration contents are already there then just do the below command in production:
rails db:schema:load RAILS_ENV=production.
Related
I have multiple databases. All the migrations for the main database human_development runs fine. The second database is called animals and the migrations fail.
database.yml:
default: &default
adapter: postgresql
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
encoding: unicode
user: blah
development:
<<: *default
database: human_development
animals:
<<: *default
database: animals
Migrations that are failing:
class SomeTable < ActiveRecord::Migration[5.2]
def change
ActiveRecord::Base.establish_connection("animals")
create_table :some_table, id: :uuid do |t|
t.string :type
t.timestamps
end
ActiveRecord::Base.establish_connection(Rails.env)
end
end
I have also tried the following, non worked:
def connection
ActiveRecord::Base.establish_connection("animals").connect
#ActiveRecord::Base.establish_connection("animals".to_sym).connect
end
establish connection out side of the change
ActiveRecord::Base.establish_connection("animals").connect
# also tried with to_sym
If I run "rails db:migrate", passing the database name as a string I get the following error:
rake aborted!
ActiveRecord::AdapterNotSpecified: database configuration does not specify adapter
.../db/migrate/2019_some_tables.rb:2:in
and if I run the rails db:migrate with to_sym I get the following error:
-- create_table(:some_table, {:id=>:uuid})
rake aborted!
ActiveRecord::StatementInvalid: PG::ConnectionBad: connection is closed: SELECT pg_advisory_unlock
Caused by:
PG::ConnectionBad: connection is closed
Caused by:
StandardError: An error has occurred, this and all later migrations canceled:
PG::ConnectionBad: connection is closed: ROLLBACK
Caused by:
ActiveRecord::StatementInvalid: PG::ConnectionBad: connection is closed: ROLLBACK
Caused by:
PG::ConnectionBad: connection is closed
The migration file should be the same for all databases
class SomeTable < ActiveRecord::Migration[5.2]
def change
create_table :some_table, id: :uuid do |t|
t.string :type
t.timestamps
end
end
end
then in your console you run
# for the main db
rails db:migrate
# for the animals db
RAILS_ENV=animals rails db:migrate
#Eyeslandic Thank you so much, that helped a lot!
In case anyone else runs into the same problems. Looks like rails 6 is going to have a better solution for this, but meanwhile, here are additional changes I had to make:
database.yml: I wanted to keep the migrations in a separate folder:
├── db
│ ├── migrate
│ ├── schema.rb
│ └── seeds.rb
├── animals_db
│ └── migrate
animals:
<<: *default
database: animals
migrations_paths: animals_db/migrate
Create a new environment: config/environments/animals.rb
Change config/secrets.yml to include new environment
Generate secret: RAILS_ENV=animals rake secret
Save the secret in .env file or export it
Create the database: rails db:create RAILS_ENV=animals
Create the migration in animals_db but here is the catch. I had to include the following in def change
def change
create_table :some_table, id: :uuid do |t|
enable_extension "uuid-ossp"
enable_extension "pgcrypto"
t.string :type
t.timestamps
end
end
Run the migration: rails db:migrate RAILS_ENV=animals
You may need to change config/cable.yml as well to include new environment
Hope this helps. Looking forward to see how rails 6 is going to improve this
Every time I run rake db:migrate, my schema file is always changed to this
# A bunch of comments up here
ActiveRecord::Schema.define(version: WHATEVER_MY_LATEST_VERSION_IS) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
end
It will update the schema version, and run the migration. The tables will be created, indexes are created. It just leaves my schema.rb with nothing but this enable_extension in it. Running rake db:schema:dumpwill create the same schema file. I'm running on rails 4.1.10.
EDIT I do have the pg gem installed (0.18.1). There's no outstanding migrations. This app has been in production for over 2 years now. It's been doing this issue for the last year or so, but we only do a new migration maybe twice a year so we haven't put much effort in to it until now. My DB yml is pretty standard:
defaults: &defaults
encoding: utf8
adapter: postgresql
database: <%= ENV['DATABASE_NAME'] %>
username: <%= ENV['DATABASE_USERNAME'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
host: <%= ENV.fetch('DATABASE_HOST', 'localhost') %>
min_messages: WARNING
development:
<<: *defaults
Problem
rake db:migrate is not creating tables in my MySQL database. (Yes, I have read all similar posts, and implemented their suggestions, please continue reading.)
Code
database.yml:
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
host: localhost
port: /tmp/mysql.sock
development:
<<: *default
database: asreport
Line from gemfile (yes, I already gem install'd it too):
gem 'mysql2', '~> 0.3.20'
/appfile/db/migrate/create_users.rb (I've also tried making the second line 'def up'):
class CreateUsers < ActiveRecord::Migration
def up
create_table :users do |t|
t.string :username
t.string :password
t.integer :usertype
t.string :salt
t.timestamps
end
end
end
After I run rake db:drop, rake db:create to refresh, rake db:migrate --trace reads (after this output, 'show tables' in mysql still only shows schema_migrations):
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:migrate
** Invoke db:_dump (first_time)
** Execute db:_dump
** Invoke db:schema:dump (first_time)
** Invoke environment
** Invoke db:load_config
** Execute db:schema:dump
What I've Tried
First of all, I know that I am connecting to MySQL via Ruby, as db:drop create does indeed create the database itself, just not the table.
I've read all the relevant stack overflow posts I could find on the issue. I've tried rollback, dropping my database directly on SQL, and db:drop/create.
I've tried deleting and recreating my migration script too.
I've run db:migrate multiple times (by itself and after db:drop/create's, rollback's, resets), but the schema_migrations always has 0 entries and my schema.rb file is on version: 0.
You're not following the naming conventions outlined in the Rails Guides.
Specifically, this:
2.1
Creating a Standalone Migration Migrations are stored as files in the db/migrate directory, one for each migration class. The name of
the file is of the form YYYYMMDDHHMMSS_create_products.rb, that is to
say a UTC timestamp identifying the migration followed by an
underscore followed by the name of the migration. The name of the
migration class (CamelCased version) should match the latter part of
the file name. For example 20080906120000_create_products.rb should
define class CreateProducts and
20080906120001_add_details_to_products.rb should define
AddDetailsToProducts. Rails uses this timestamp to determine which
migration should be run and in what order, so if you're copying a
migration from another application or generate a file yourself, be
aware of its position in the order.
Go ahead and try a dummy migration to see the file name convention.
$ bin/rails generate migration AddPartNumberToProducts part_number:string
I'm having a problem with my application on Heroku, and in order to determine whether it is specific to my production environment or specific to Heroku itself I am running my production environment locally on my machine with rails s -e production
When I try to load my posts index, I get the following error:
PG::UndefinedTable: ERROR: relation "posts" does not exist
LINE 1: SELECT "posts".* FROM "posts"
^
: SELECT "posts".* FROM "posts"
PG::UndefinedTable: ERROR: relation "posts" does not exist
LINE 1: SELECT "posts".* FROM "posts"
What's weird is my posts index works fine on Heroku, as well as in development and in test. When I run bundle exec rake db:create:all I get the follow output:
project_development already exists
project_test already exists
project_production already exists
My schema is as follows:
create_table "posts", force: true do |t|
t.string "title"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "author_id"
t.boolean "published"
end
When I fire up rails db in the command line, I can see the table as expected when I run \dt:
public | posts | table | Thomas
However when I fire it up with ENV=production and run \dt I get the following:
Schema | Name | Type | Owner
--------+-------------------+-------+--------
public | schema_migrations | table | Thomas
I've tried running ENV=production rake db:schema:load and that does not solve the problem.
For reference, here is my database.yaml:
development:
adapter: postgresql
encoding: utf8
database: project_development
pool: 5
username:
password:
test:
adapter: postgresql
encoding: utf8
database: project_test
pool: 5
username:
password:
production:
adapter: postgresql
encoding: utf8
database: project_production
pool: 5
username:
password:
The production database created from the database.yml file with rake db:create:all is created locally on your machine, not on heroku.
Heroku automatically infers the database config for the production environment, and creates it when you run git push heroku master for the first time.
The error message about posts table not existing is because of not running migrations on heroku. Run heroku run rake db:migrate to apply the migrations to the production database on heroku.
Also, you don't need to have the production section of the database.yml on your local environment.
Do refer to https://devcenter.heroku.com/articles/getting-started-with-rails4 while working for the first time with heroku; it is comprehensive and very helpful.
EDIT
The actual problem was to get the local production database to work.
Solution was to apply the migrations correctly with rake db:migrate RAILS_ENV=production
Running rake db:migrate followed by rake test:units yields the following:
rake test:functionals
(in /projects/my_project)
rake aborted!
SQLite3::SQLException: index unique_schema_migrations already exists: CREATE UNIQUE INDEX "unique_schema_migrations" ON "ts_schema_migrations" ("version")
The relevant part of db/schema.rb is as follows:
create_table "ts_schema_migrations", :id => false, :force => true do |t|
t.string "version", :null => false
end
add_index "ts_schema_migrations", ["version"], :name => "unique_schema_migrations", :unique => true
I'm not manually changing this index anywhere, and I'm using Rails' default SQLite3 adapter with a brand new database. (That is, running rm db/*sqlite3 before rake db:migrate doesn't help.)
Is the test:units task perhaps trying to re-load the schema? If so, why? Shouldn't it recognize the schema is already up to date?
In SQLite, index name uniqueness is enforced at the database level. In MySQL, uniqueness is enforced only at the table level. That's why your migrations work in the latter and not the former: you have two indexes with the same name on different tables.
Rename the index, or find and rename the other unique_schema_migrations index, and your migrations should work.
In your database.yml file are your environments setup up to connect to different databases for Development and Test?
IE:
development:
adapter: sqlite3
database: db/dev.sqlite3
timeout: 5000
test:
adapter: sqlite3
database: db/test.sqlite3
timeout: 5000
Try to search if your schema.rb file does not contain other declarations that create an index with the same name: unique_schema_migrations