I created the following migration script (using bundle exec rails generate migration CreateSequenceStudentId):
class CreateSequenceStudentId < ActiveRecord::Migration[6.0]
def change
# Based on: https://schmijos.medium.com/execute-sql-in-rails-migrations-cdb26f51c683
execute 'CREATE SEQUENCE IF NOT EXISTS student_id;'
end
end
Then executed bundle exec rails db:migrate RAILS_ENV=test and it completed. I can access the sequence using psql student_test -c"select nextval('student_id')". Running psql student_test -c"select * from schema_migrations sm" lists 20201122013457 at the very last. No problems so far.
I then wrote the following spec to access the sequence:
sql = "select nextval('student_id')"
p Student.connection.select_all(sql)
And it failed:
# --- Caused by: ---
# PG::UndefinedTable:
# ERROR: relation "student_id" does not exist
# LINE 1: select nextval('student_id')
And I executed psql student_test -c"select nextval('student_id')" one more time and got:
ERROR: relation "student_id" does not exist
LINE 1: select nextval('student_id')
bundle exec rails db:migrate:status RAILS_ENV=test gives:
Status Migration ID Migration Name
--------------------------------------------------
...
up 20201122013457 Create sequence student
So it indicates the migration executed successfully.
psql student_test -c"select * from schema_migrations sm" gives:
version
----------------
20201122013457
20191209013052
20191220005953
20191225001051
20191225001255
20191225001458
...
The new script was executed first. This smells fishy.
Sounds like the migration ran successfully when using db:migrate but not when running rspec. Appreciate any pointers on what I could be doing wrong.
PS: Based on this solution, I have checked if the script name is unique and it is.
I was able to fix your issue by running exact below commands. I found the answer here.
RAILS_ENV=test rake db:drop
RAILS_ENV=test rake db:create
RAILS_ENV=test rake db:migrate
UPDATE:
I found also the way to fix rails db:reset command, you just need to add line config.active_record.schema_format = :sql in your application.rb so info about sequence will be stored in structure.sql. Please take a look that with default schema dump :ruby info about seqeunce is not stored in schema.rb file.
Important: make sure to firstly create structure.sql with rails db:migrate and then run rails db:reset. After just rails db:migrate I'm still getting the error you want to fix.
Related
I have the current migration
class CreateSlugSequence < ActiveRecord::Migration[5.2]
def up
execute <<-SQL
CREATE SEQUENCE slug_sequence
SQL
end
def down
execute <<-SQL
DROP SEQUENCE slug_sequence
SQL
end
end
I run rails db:migrate
Enter rails c (development mode)
Run ActiveRecord::Base.connection.exec_query("select nextval('slug_sequence')")[0]['nextval']
And get the expected value
But if I enter rails c in test mode, for some reason, the sequence table does not exist
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "slug_sequence" does not exist
I ran ActiveRecord::Migrator.current_version, to check what was the last migration applied and it returns the latest version.
Thanks for the help in advance.
I recommended dropping the test db and recreating it. Although these should remain in sync they sometimes do not and you have to do manual steps to get them together.
RAILS_ENV=test rake db:reset
Weird that it is not working with that, would be interesting to drop a pry debugger in that task and see what is going on. https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/databases.rake#L122
Manual steps
RAILS_ENV=test rake db:drop
RAILS_ENV=test rake db:create
RAILS_ENV=test rake db:migrate
I found the way to fix rails db:reset command, you just need to add line config.active_record.schema_format = :sql in your application.rb so info about sequence will be stored in structure.sql. Please take a look that with default schema dump :ruby info about seqeunce is not stored in schema.rb file.
Important: make sure to firstly create structure.sql with rails db:migrate and then run rails db:reset. After just rails db:migrate I'm still getting the error you want to fix.
I've blown away my database and am now having problems migrating back to a working database.
The error looks the same as other questions already posted, but I can't figure out how to solve it. What can I change to get my environment back? How did it get like this?
I've verified the database does indeed exist, but the tables are not being created by the migrations step.
The error looks like:
$ RAILS_ENV="development" bundle exec rake db:test:prepare
rake aborted!
PG::Error: ERROR: relation "documents" does not exist
LINE 4: WHERE a.attrelid = '"documents"'::regclass
^
Note: I get the same result attempting any of:
$ bundle exec spec
$ RAILS_ENV="development" bundle exec rake db:migrate
$ RAILS_ENV="development" bundle exec rake db:test:prepare
$ RAILS_ENV="development" bundle exec rake db:schema:load
THEORY ONE:
It may have to do with the way my migrations are written: I have a class Paragraph:
class Paragraph < ActiveRecord::Base
belongs_to :document
validates_presence_of :document, :document_index
validates_uniqueness_of :document_index, scope: [:document_id]
However, originally when developing this I added the model "document" LAST. Should I somehow change the order of the migrations?
THEORY TWO:
When I run any of these with "production" they work fine (except for my tests of course).
Therefore the config error is influenced in some way by the database configuration.
What say you?
Before migrations are run, the whole Rails environment is initialized. So probably there is code executed during initialization process that tries to use the missing relation.
Run the rake task with --trace option to track this code down.
I'm setting up an existing rails app on a new workstations. When I try to rake db:migrate, I get this strange error before any attempt to even create the first table (yes, I started with rake db:create):
$ bundle exec rake db:migrate
rake aborted!
Mysql2::Error: Table 'myapp_dev.usage_roles' doesn't exist: SHOW FULL FIELDS FROM `usage_roles`
# ... followed by a long stack trace
I can't guess why the rake task is trying to show fields from any table before any should exist. I don't even see much mention of this table in the app. Here's the complete grep:
$ grep -r usage_roles .
Binary file ./.git/index matches
./app/models/usage/role.rb: self.table_name = 'usage_roles'
./app/models/usage/user.rb: where(" usage_roles.name in (?)", Usage::Role::SUPPORT_ROLES)
./coverage/index.html: <code class="ruby"> self.table_name = 'usage_roles'</code>
./coverage/index.html: <code class="ruby"> where(" usage_roles.name in (?)", Usage::Role::SUPPORT_ROLES)</code>
./db/migrate/20130112104233_create_usage_roles.rb: execute('CREATE VIEW usage_roles AS SELECT
./db/migrate/20130112104233_create_usage_roles.rb: * FROM clu_enums.usage_roles;')
./db/migrate/20130112104233_create_usage_roles.rb: execute('DROP VIEW IF EXISTS usage_roles;')
I think your issue is directly related to how Factorygirl handles databases. When you set factory_girl_rails to require:false that seems to be the solution.
Take a look at this FactoryGirl screws up rake db:migrate process
I am very new in ruby-on-rails. I have doubt in rake. create function is create a new db. After that, we want to run some commands like
rake db:load
rake db:data:load
rake db:schema:load
rake db:migrate
rake db:seed
But why we want to run this cmds after create the db and what function of the about cmd.
Thanks for your advice.
You can use rake -T to get the description of each task:
$ rake -T | grep db
rake db:create # Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)
rake db:drop # Drops the database for the current Rails.env (use db:drop:all to drop all databases)
rake db:fixtures:load # Load fixtures into the current environment's database.
rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false).
rake db:migrate:status # Display status of migrations
rake db:rollback # Rolls the schema back to the previous version (specify steps w/ STEP=n).
rake db:schema:dump # Create a db/schema.rb file that can be portably used against any DB supported by AR
rake db:schema:load # Load a schema.rb file into the database
rake db:seed # Load the seed data from db/seeds.rb
rake db:setup # Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first)
rake db:structure:dump # Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql
rake db:version # Retrieves the current schema version number
I this what you were asking about?
EDIT:
You can read more about what migrations are for here: http://guides.rubyonrails.org/migrations.html
EDIT 2:
rake db:migrate allows you to update the DB schema in a "sane" way: you can create a new migration (read the guides!) and add a new column for example, add an index, rename a column, etc. - migrations allow you to "travel" back and forth in "time" - you can run the migration and rollback it later.
When you generate a new migration:
$ rails g migration add_new_column_to_some_table you will be able to run rake db:migrate later on to apply to changes you want (of course you have to write the body of this generated migration).
I STRONLY advise you to read the guides though :)
EDIT 3:
add_column :users, :price, :float, for example, will add price column to the users table, the type of the column will be float (float isn't a best idea to store money related things BTW!). This column will be NULL by default.
EDIT 4:
Information about which migrations were run is stored in schema_migrations table: running migration for the first time will add a new record in this table with version of this migration (date + some random numbers from the name of the file). Rollbacking a migration will remove this record. Running a migration twice will not have any effect.
Simply put, db:migrate doesn't destroy existing data you have in your database. so running migrations and that rake task allows your data to exist from changes you make.
Workflow in words
You create an empty data base.
You will want to add a table of data for your first model into the database. This is done by editing a file in db/migrate
Now you want a second model, so you create your model and edit the migration file in db/migrate that was created for you
The easiest way to update your database without destroy any of the existing data, is to run bundle exec rake db:migrate. This adds the contents of the second migration file into the db and won't hurt existing data.
Example workflow after creating a project:
bundle exec rake db:create:all
bundle exec rails generate scaffold Users name:string email:string
bundle exec rake db:migrate
At this stage, bundle exec rails s and go to localhost:3000/users/new and create a new user.
bundle exec rails generate scaffold Posts title:string body:text
bundle exec rake db:migrate
Back in your browser go to localhost:3000/users and you should still see the user you created.
I'm working through the rails tutorial and have gotten stuck. Starting at Listing 8.16 I have made the following modifications to <timestamp>_add_remember_token_to_users.rb:
class AddRememberTokenToUsers < ActiveRecord::Migration
def change
add_column :users, :remember_token, :string
add_index :users, :remember_token
end
end
The guide then says to update dev & test db as usual:
$ bundle exec rake db:migrate
$ bundle exec rake db:test:prepare
My User test for the *remember_token* is still failing so I took a look at the user table in dev and tests database with command line sqlite3. They look like this:
sqlite> .schema users
CREATE TABLE "users" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"name" varchar(255),
"email" varchar(255),
"created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL,
"password_digest" varchar(255));
CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email");
It seems like my migration has not been run yet but I do not know how to force it to run.
Try to rebuild your database structure(WARNING: all db-data will be lost):
rake db:drop:all
rake db:create:all
rake db:migrate
If you use Rails < 4.1, don't forget to prepare test database:
rake db:test:prepare
This is the easiest solution since you are working with tutorial. However in production or having important data in development you should take time to investigate the issue. In this case you most likely had created an empty migration, ran rake db:migrate, then added instructions to the migration, so you don't see a new field and further rake db:migrate does nothing. To resolve this issue you need to comment your change instructions, perform rake db:rollback, uncomment instructions and then rake db:migrate to apply instructions you missed.
I had the same issue as the initial question. $ bundle exec rake db:migrate wasn't adding remember_token to the .db and Latha Doddikadi's answer worked for me.
I did:
rake db:rollback
and then:
$ bundle exec rake db:migrate
which added the remember_token field to the database followed by:
bundle exec rspec spec/models/user_spec.rb
which passed.
Finished in 0.92841 seconds
21 examples, 0 failures
Roll back and then re run the migration it might work.
rake db:rollback
And after rolling back re run your migrations again.
I had a bizarre case of the last migration simply refusing to run. I'd created the migration file manually. So I deleted it and remade the migration using
rails g migration ...
and copied the code into the new file and it ran.
I didn't discover why manually creating that file didn't work; all I know is doing it the 'right/rails way' fixed the issue.
Leaving this here in case it helps someone else.