I'm trying out a simpler setup for using Sinatra with ActiveRecord and I am running into some puzzling problems and would love another set of eyes on it. I will give all the relevant files:
database.yml:
development:
adapter: sqlite3
database: db/development.sqlite3
test:
adapter: sqlite3
database: db/test.sqlite3
production:
url: <%= ENV['DATABASE_URL'] %>
Rakefile:
require_relative "demo_app"
require 'sinatra/activerecord/rake'
require 'rake/testtask'
Rake::TestTask.new do |t|
t.pattern = "test/*_test.rb"
end
test_helper.rb:
ENV['RACK_ENV'] = 'test'
ENV["SINATRA_ENV"] = "test"
require_relative '../demo_app'
require 'minitest/autorun'
require 'rack/test'
ActiveRecord::Migration.maintain_test_schema!
Migration file:
class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :name
t.date :dob
t.string :gender
t.string :gender
t.integer :zipcode
end
end
end
Now, I want to run tests against the test database. When I try to do
rake db:create RAILS_ENV=test - it creates a development.sqlite3
rake db:migrate RAILS_ENV=test - same + runs migration
I know that I am using ActiveRecord outside of Rails so I suspect the problem lies somewhere relating to the processing of database.yml or some environment variable or something. But I can't figure it out.
Thoughts?
Try RACK_ENV instead of RAILS_ENV:
$ rake db:create RACK_ENV=test
Or:
$ RACK_ENV=test rake db:create
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
I'm using Ruby 2.2.2 and Rails 4.2.3.
The commands I did are:
rails generate scaffold User name:string email:string
bundle exec rake db:migrate
The error I got is:
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
undefined method `strong' for #<ActiveRecord::ConnectionAdapters::TableDefinition:0x00000005b72028>/home/clemant/tutorials/test2/db/migrate/20150709221657_create_users.rb:5:in `block in change'
My migration file:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.strong :email
t.timestamps null: false
end
end
end
My database.yml file is:
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
Any idea how to fix this?
In your migration file, you have written: t.strong :email.
It should be rectified as follows:
t.string :email
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.timestamps
end
# Create sample User
User.create :name => "TestUser"
end
end
When run rake db:create and rake db:migrate command
In development database it creates sample user but not in test database. I want this user in test database also. any reason?
Also tried rake db:migrate RAILS_ENV=test.
First you should run the following command rake db:test:prepare in order to "prepare" the test database.
Finally, I recommend using the following file db/seeds.rb if you wish to add new records in your database.
In the db/seeds.rb file:
User.create(name: "TestUser")
Run:
rake db:seed
rake db:seed RAILS_ENV=test # for test env
If you're looking to test a user why not create a fixture or use rspec for testing something like this? The above code is bad practice. I would do something like this
migration file.
def self.up
create_table :users do |t|
t.string :name
t.timestamps
end
end
Depending on your testing stack I would setup a fixture like so(yml fixture)
david:
name: David Smith
You could also use rspec with factory girl which makes testing alot easier in rails.
I am trying to run a migration to a separate DB in Rails, using establish_connection. I have something like this in the migration file:
def change
ActiveRecord::Base.establish_connection("user_#{Rails.env}")
ActiveRecord::Base.initialize_schema_migrations_table
create_table "users", :force => true do |t|
t.string "email",
end
In the yml I have this config:
user_development:
adapter: postgresql
encoding: unicode
database: MyApp_user_development
pool: 5
host: localhost
username: xxx
password: xxx
Also I have defined the User Model like this:
class User < ActiveRecord::Base
establish_connection "user_#{Rails.env}"
[...]
end
Now, the DB exists but when running rake db:migrate I get this error:
== CreateUserOnSeparateDb: migrating =========================================
rake aborted!
An error has occurred, this and all later migrations canceled:
connection is closed
Does any of you have any idea what is going on?
I have also tried to move the establish_connection call into a connection method in the migration file. In this case the table is created on migrate but then I get the same error (so somehow failing on other migrations) and by the way it does not create the schema_migrations table...
Any help?
Resolved above issue by following below steps.
class AddCustomTbl < ActiveRecord::Migration
def connection
ActiveRecord::Base.establish_connection(Rails.env).connection
end
def up
# Connection with user_#{Rails.env}
oldEnv = Rails.env
Rails.env = "user_#{Rails.env}"
ActiveRecord::Base.establish_connection(Rails.env)
create_table "users", :force => true do |t|
t.string "email"
end
# Connection with Rails.env
Rails.env = oldEnv
ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]
end
def down
# Connection with user_#{Rails.env}
oldEnv = Rails.env
Rails.env = "user_#{Rails.env}"
ActiveRecord::Base.establish_connection(Rails.env).connection
drop_table :users
# Connection with Rails.env
Rails.env = oldEnv
ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]
end
end
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