I'm trying to perform database related operations on my newly upgraded app(Rails 5) and I'm unable to perform destructive database commands locally.
rails db:reset or rails db:drop .
The trace results with the following data,
rails db:drop --trace
** Invoke db:drop (first_time)
** Invoke db:load_config (first_time)
** Execute db:load_config
** Invoke db:check_protected_environments (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config
** Execute db:check_protected_environments
rails aborted!
ActiveRecord::NoEnvironmentInSchemaError:
Environment data not found in the schema. To resolve this issue, run:
bin/rails db:environment:set RAILS_ENV=development
What I've tried so far are,
Setting bin/rails db:environment:set RAILS_ENV=development, doesn't change anything still the error occurs.
Setting Environment variable manually to development.
None of these helped. I'm Looking for a fix or workaround.
Two Fixes to ActiveRecord::NoEnvironmentInSchemaError
The other answers here describe the problem very well, but lack proper solutions. Hoping this answer helps someone experiencing this issue.
Why this error is happening
This incorrect error message is a result of this pull request designed to prevent destructive actions on production databases. As u/pixelearth correctly points out, Rails 4.2 defines the 'key' field in the ar_internal_metadata table to be an integer, and Rails 5+ (including Rails 6) expects this to be a string with the value, environment. When Rails 5 and Rails 6 run this safety check, they incorrectly raise an ActiveRecord::NoEnvironmentInSchemaError as the code is incompatible with the Rails 4 schema format.
Fix #1: Override the safety check in Rails 5+
**Please remember, the safety check was implemented as a result of so many users dropping their production databases by accident. As the question describes, the operations are destructive.
From the terminal:
rails db:drop RAILS_ENV=development DISABLE_DATABASE_ENVIRONMENT_CHECK=1
# and/or
rails db:drop RAILS_ENV=test DISABLE_DATABASE_ENVIRONMENT_CHECK=1
As noted here, the DISABLE_DATABASE_ENVIRONMENT_CHECK=1 flag disables the environment check. After, you can run a rake db:create RAILS_ENV=development, for example, to recreate your database with the correct schema in the ar_internals_metadata table.
Fix #2: Revert to Rails 4, drop database, go back to Rails 5+ and recreate
From the terminal:
git log
# grab the commit hash from before the upgrade to Rails 5+
git checkout **hash_from_rails_4**
rake db:drop RAILS_ENV=development
rake db:drop RAILS_ENV=test
git checkout master
# now things should work
rails db:migrate
Again, please ensure you are not pointing at a production database when overriding this functionality. Alternatively, it would be possible to directly modify the schema of this table. If you're experiencing this error in production, you may need to take this approach.
This happened because, for some reason, your table ar_internal_metadata got deleted or changed.
If you cannot drop the database via the command line, you need to do it via your DBMS or database client.
Then, just run rails db:create db:migrate to create and run the migrations.
For posterity, my issue was that this schema was generated by a rails 4 app and the current app using it is rails 5. With rails 5 the structure of the ar_internal_metadata table has changed slightly. The key field needs to be a string and contain the word 'environment', not an integer. This error only goes away when this is changed.
It should look like this in Rails 5
ie, change the type of ar_internatl_metadata #key to string...
My situation is a bit uncommon involving a rails 4 app and a rails 5 app sharing the same db. When I need to "update", I have a task:
puts "Modifying Rails 4 schema to fit Rails 5 schema"
file_name = "./db/schema.rb"
rails_4_ar_internal_metadata = 'create_table "ar_internal_metadata", primary_key: "key", force: :cascade do |t|'
rails_5_ar_internal_metadata = 'create_table "ar_internal_metadata", primary_key: "key", id: :string, force: :cascade do |t|'
new_schema = File.read(file_name).gsub(rails_4_ar_internal_metadata, rails_5_ar_internal_metadata)
File.write(file_name, new_schema)
Console rails
bin/rails db:environment:set RAILS_ENV=development
I had
bundle exec rake db:drop
rake aborted!
ActiveRecord::NoEnvironmentInSchemaError:
Environment data not found in the schema. To resolve this issue, run:
rails db:environment:set RAILS_ENV=development
And, indeed, simply running rails db:environment:set RAILS_ENV=development made the problem go away.
Why did this happen?
It happened because I tried to drop the database and create it / migrate it, however, I had a syntax error in the migration (datatype and column name in the wrong places). Check your migration file for any silly errors
Specifically I had
t.submitted :boolean, default: false
instead of
t.boolean :submitted, default: false
Related
Running tests on Rails on the built Sample App (Michael Hartl Rails 5), When running tests I get the above error, which suggests it can't find the table 'users', it's available in my db migrate folder and also listed in the development.sqlite3 file, So not sure what the issue is
Tried the recommended fixes running rake db:test:prepare, rails db:migrate:reset testing to see if User.new(name: 'foo') creates a user neither have fixed the problem and the latter creates fine in the console so can't understand why it can't find the table
_create_users.rb
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps
end
end
end
tests to run errors run when attempting 'rails test:mailers' and more when using 'rails test'
db:migrate
SQLite
It's important to remember that each environment in Rails has its own database. Just because your application is working when you're doing development (RAILS_ENV=development), it doesn't mean the database is there when running tests (RAILS_ENV=test).
You may simply need to prepare your test database (create it and migrate it):
# Drop any test DB you already have
bundle exec rake db:drop RAILS_ENV=test
# Create a clean fresh one
bundle exec rake db:create RAILS_ENV=test
# Import the Schema from your schema.rb, rather than run all migrations
bundle exec rake db:schema:load RAILS_ENV=test
If you do the above and then run your tests, they should work as expected.
I would like to add one more field to accounts table.
So I have done this
1) padrino g migration AddPhoneNumberToAccounts phone_number:string
This make a migration file named
038_add_phone_number_to_accounts.rb
2) and I migrated.
padrino rake db:migrate -e development
But it make errors
/Users/whitesnow/.rvm/gems/ruby-2.4.1/gems/sequel-4.46.0/lib/sequel/extensions/migration.rb:601:in `block in get_migration_files': Missing migration version: 6 (Sequel::Migrator::Error)
from /Users/whitesnow/.rvm/gems/ruby-2.4.1/gems/sequel-4.46.0/lib/sequel/extensions/migration.rb:601:in `upto'
from /Users/whitesnow/.rvm/gems/ruby-2.4.1/gems/sequel-4.46.0/lib/sequel/extensions/migration.rb:601:in `get_migration_files'
....
How to solve this? sometimes I didn't get this errors but it doesn't update table either.
Thanks.
This is odd. I definitely am specifying the adapter and it even prints the hash out with puts in the top line of the rake task. db:migrate works too.
$ rake db:create
{"adapter"=>"mysql2", "encoding"=>"utf8", "reconnect"=>false, "database"=>"craigslist_development", "pool"=>5, "username"=>"root", "password"=>"splitzo", "host"=>"localhost"}
rake aborted!
database configuration does not specify adapter
any ideas?
Let me know if you need more info.
UPDATE:
I am sure the environment is set correctly as it works when I run rake db:migrate
I notice that it is running the ActiveRecord's establish_connection twice and the second time it is not getting the hash. I added some debugging code
spec = spec.symbolize_keys
puts 'test:' + spec.key?(:adapter).to_s
and I get this:
{"adapter"=>"mysql2", "encoding"=>"utf8", "reconnect"=>false, "database"=>"appname_development", "pool"=>5, "username"=>"user", "password"=>"password", "host"=>"localhost"} (just prints hash object)
test:true (first time)
test:false (second time)
rake aborted!
database configuration does not specify adapter
It's essentially just this and since it works with other tasks I assume the format is good with no odd whitespace issues etc:
development:
adapter: mysql2
encoding: utf8
reconnect: false
database: appname_development
pool: 5
username: user
password: password
host: localhost
It must be an issue with the logic in my Rakefile?
As #Taryn East said, you must pass in the RAILS_ENV to rake.
rake db:create RAILS_ENV=development should do the trick.
Recently, I've started diving into Ruby MVCs, in order to find the best, fastest, most minimal framework to build my app. Being unsatisfied with Rails, I decided to try out Padrino. I'm also trying out Outside-in TDD for a full app for the first time, so being able to write tests for all components is critical. Unfortunately, I cannot get past making models in Padrino, so I'm wondering if it's just a cause of beta software, or just error on my part.
I start off by creating my project with Cucumber and RSpec for testing and Sequel for my ORM.
$ padrino g project test -d sequel -t cucumber -c sass -b
Next, I create some model and migration:
$ padrino g model user
# ./db/migrate/001_create_users.rb
Sequel.migration do
change do
create_table :users do
primary_key :id
String :name
String :password
end
end
end
Next, of course, comes the spec. For sake of example, just something simple:
# ./spec/models/user_spec.rb
require 'spec_helper'
describe User do
it 'can be created' do
user = User.create
end
end
Now, migrate and run the spec:
$ padrino rake sq:migrate:up
$ rspec spec
F
Failures:
1) User can be created
Failure/Error: user = User.create
Sequel::DatabaseError:
SQLite3::SQLException: no such table: users
# ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.00169 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:4 # User can be created
This is very confusing. It was at this point that I thought going into the Padrino console would help me solve this strange issue. I was wrong.
$ padrino c
> User.create
=> #<User #values={:id=>1, :name=>nil, :password=>nil}>
> User.all
=> [#<User #values={:id=>1, :name=>nil, :password=>nil}>]
Fair enough results, but then I try it with the test environment:
$ padrino c -e test
> User.create
Sequel::DatabaseError: SQLite3::SQLException: no such table: users
I know that in RoR, to get integrated models to run, you have to do something like rake db:test:prepare, but doing padrino rake -T doesn't seem to reveal any equivalent (tested with Sequel, DataMapper, and ActiveRecord; none seem to have the db:test:prepare). So, my question is: how do I get integrated database tests running within Padrino?
From this forum post, I discovered why db:test:prepare is this weird, arbitrary rake task one needs to run: it has to do with the test environment (versus development and production). In Padrino, this translates to the following code, which is a bit more obscure, but more intuitive as well:
$ padrino rake sq:migrate:up -e test
This tells Padrino to create the table for the test database, which allows the spec(s) to pass.
I've never had anything but success w/ Rails migrations, so this one is especially perplexing to me. I have a migration that I just wrote, it's fairly simple, but when I try and run it (for the first time, or after rolling back and trying again), there is no output to the console for a few seconds, the job ends, and no change has occurred to my DB, other than checking rake db:migrate:status will show the migration has run (or, it thinks it has).
Migration code is here:
class AddNotesToCases < ActiveRecord::Migration
def up
add_column :cases, :notes, :text
end
def down
remove_column :cases, :notes
end
end
db is PostGres, Rails is 3.0.9, rake is 0.9.2.2
EDIT **
per request, the results of a trace on the rake call are:
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:migrate
** Invoke db:schema:dump (first_time)
** Invoke environment
** Execute db:schema:dump
FWIW, I also have tried rewriting the migration to use a String instead of Text datatype, and also have tried using the def change rather than up/down. No joy on any of them.
Gah, ok, after re-generating the file from scratch I realized when going from the change version to the up/down version, I'd typeoed the methods and forgot the 'self' on them. :|
def self.up
worked where my code didn't.
The author must have been using Rails version prior to 3.1 because after that singleton methods were no longer needed.