Removing timestamp fields from the schema - ruby-on-rails

I had used default generator to create some tables and they all had that t.timestamp in their definition so the schema that was created also has created_at and updated_at fields.
Now I am told that I don't need those two fields in my schema so I went to the original create_table* files and took out t.timestamp line from them and ran the db:migrate and schema:load commands
But still when I go to my schema.rb file I can see they are still there.
Is there anything wrong I am doing here?

Run
rails g migration remove_timestamps_from_table created_at updated_at
with table being your model's name. Since this is following the pattern remove x from y, rails is smart enough to generate the appropriate migration for you.
Then run
rake db:migrate
to update your development database and
rake db:test:prepare
to prepare the test database, and you're all set!
Read more on migrations here. If you are still having trouble, consider restarting your rails server or database server.

Related

What is the purpose of sqlite_sp_functions in Rails schema.rb?

Like some others, I am having trouble with an error
"ActiveRecord::StatementInvalid: SQLite3::SQLException: object name
reserved for internal use: sqlite_sp_functions: CREATE TABLE
"sqlite_sp_functions" ("name" text, "text" text)"
when running rake test on a Rails project.
The offending lines in schema.rb are:
create_table "sqlite_sp_functions", id: false, force: true do |t|
t.text "name"
t.text "text"
end
The suggestions on the previous query about this involved editing schema.rb or deleting that file & regenerating it, but schema.rb (and the offending code) are regenerated on each migration (plus, I don't want to delete Rails-generated code without knowing the implications), so that's not really a satisfactory solution.
So what is the sqlite_sp_functions table for, and how can I get Rails to generate a schema.rb file that doesn't break rake test for the project?
as per https://stackoverflow.com/a/25077833/601782:
Add the following config line to config/application.rb or in config/environments/development.rb:
ActiveRecord::SchemaDumper.ignore_tables = /^sqlite_*/
This will ignore all tables starting with "sqlite_" in your database during the schema dump.
Try removing the offending lines from your schema.rb and then issue:
RAILS_ENV=test rake db:reset
which will completely nuke your testing database but you shouldn't care anyway. You are not supposed to run migrations for test environments. Migrations are meant to be small (reversible) steps for environments that hold data (such as production and sometimes staging/dev).
The preferred way to handle your testing DB is to use db:schema:load as part of your testing routine which will of course delete all your DB data.
Again: Please do not try this in development mode (if you have data that you set up manually) and definitely not in production.
Other than that, you could probably delete the whole sqlite_sp_functions table from your SQLite testing DB and get rid of the issue altogether. I don't think that this has anything to do with Rails (nor is Rails generating that). I believe that SQLite created this table and your schema just picks it up (as it should). Apparently the table is used to hold stored procedures of some kind.

How to keep overview of the migrations?

I have a question regarding my migrations in rails.
Normally when i want to add a colum to a model for i dont make extra migrations but instead i perform this steps:
rake db:rollback
next i change the migration file in db/migrations and rerune:
rake db:migrate
The biggest problem is that when i do this i loose my data.
Previous i wrote migrations from the command line with for example
rake g migration Add_Column_House_to_Users house:string
The problem with this approach is that my db/migrations folder afterwards get very large and not very clear! I mean at the end i dont know wich variables the object has! Im not an expert in rails and would like to ask you how to keep the overview over the migrations!Thanks
Just a minor thought - I just use the file db/migrate/schema.rb to determine whats in the database as opposed to tracking through the migrations
You definitely shouldn't use db:rollback with a table with existing data.
I have a few production RonR apps with a ton of data and there are 100+ entries in the migrations table and adding new migrations to tweak tables is the rails way to do things. Not sure what you mean by lucid, but your schema and data model are going to change over time and that is ok and expected.
One tip. The migrations are great, but they are just the beginning, you can include complex logic as needed to fix your existing data (like so)
Changing data in existing table:
def up
add_column :rsvps, :column_name_id, :integer
update_data
end
def update_data
rsvps = Rsvp.where("other_column is not null")
rsvps.each do |rsvp|
invite = Blah.find(rsvp.example_id)
...
rsvp.save
end
end
Another tip: backup your production database often (should do this anyway), but use it to test all of your migrations before deploying. I run scripts like this all the time for local testing:
mysql -u root -ppassword
drop database mydatabase_dev;
create database mydatabase_dev;
use mydatabase_dev;
source /var/www/bak/mydatabase_backup_2013-10-04-16.28.06.sql
exit
rake db:migrate

Rake task to list all migrations for a given model

On the terminal, is there a rake task to list all the migrations which have been run on a particular model? If not, how do I go about building one?
When I ran rake -T, rake db:migrate:status seemed to be the right answer, but it gave me Migration Name as one of the columns. And though the name Add logo to company does indicate Company model, not all migrations have such explicit names. Case in point being Change data type for content. I have 400 odd migration files, so this feature would be really helpful.
So, the ideal output would be:
database: abcd_development
Status Migration ID Migration Name Model Name
----------------------------------------------------------
Thanks!
If you've been sticking with the migration naming conventions, you could just pass the output of rake db:migrate:status through grep:
rake db:migrate:status | grep 'compan'
This isn't perfect, though - migration names aren't required to have anything to do with what they actually do - a migration might add the column 'name' to the 'companies' table and be named EvacuateWeaselTubes and still run just fine.
If you wanted to build a task that could overcome this problem, it would have to parse each of the migration files to see what it changed. Since there's many ways to specify a change in a migration (add_column, a create_table block, or calling execute('CREATE whatever'), for instance), you'd probably want to search for mentions of Model.table_name, then check the schema_migrations table to see if it had been run.

Marking Rails migrations as migrated

I've ended up with 9 migrations effectively duplicated. (I think this is because I installed/updated Gems and/or pulled in their migrations on both my dev and production machines, but am not entirely sure at this stage.)
I moved out one set of the duplicated 9 from the rails directories on the production server, but now that I want to db:migrate on production in order to run another migration, I'm getting:
$ bundle exec rake db:migrate RAILS_ENV=production
[DEPRECATION WARNING] Nested I18n namespace lookup under "activerecord.attributes.checkout" is no longer supported
== CreatePages: migrating ====================================================
-- create_table(:pages)
rake aborted!
An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'pages' already exists: CREATE TABLE `pages` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `title` varchar(255), `body` text, `slug` varchar(255), `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
This is because the migrations have effectively already been run.
I'd rather avoid doing db:migrate:down and db:migrate:up for each one - I think this will mean data in the production database is lost. (A couple of static pages in Spree in this case.)
Is there a way I can tell this installation of Rails to forget all outstanding migrations, effectively marking all outstanding migrations as done?
I solved it like this:
Go to the conflicting migration file.
Erase the content and save it.
Run rake db:migrate
Ctrl+Z the file to the previous state.
This was an special case, because I had copied the DB from another app, and I had conflicting migrations, and stuff.
You can add the timestamps of the migrations to the schema_migrations table. However why is that table missing from the database or missing the rows it needs?
It is likely to be the case that this particular migration has got half way through and failed, thus when you are trying to run it again the first part of the migration will not work as it has been done previously. This is a limitation of MySQL as it can't rollback migration changes that fail part of the way through. Postgres on the other hand can rollback structural changes to the database thus avoiding this issue.
By default rake db:migrate runs all the pending migrations. So, in order to get your migrations right.. for the sake ..comment out those migrations and afterwards revert those back to normal. It will ensure that you are ok in future migrations.
You can also, in a Rails console, use the ActiveRecord::SchemaMigration model to add the timestamps into the schema_migrations table.
ActiveRecord::SchemaMigration.create! version: '20210724133241'

Create Sequence In Migration Not Reflected In Schema

I have an application that requires a sequence to be present in the database. I have a migration that does the following:
class CreateSequence < ActiveRecord::Migration
def self.up
execute "CREATE SEQUENCE sequence"
end
def self.down
execute "DROP SEQUENCE sequence"
end
end
This does not modify the schema.rb and thus breaks rake db:setup. How can I force the schema to include the sequence?
Note: The sequence exists after running rake db:migrate.
Rails Migrations because they aim toward a schema of tables and fields, instead of a complete database representation including stored procedures, functions, seed data.
When you run rake db:setup, this will create the db, load the schema and then load the seed data.
A few solutions for you to consider:
Choice 1: create your own rake task that does these migrations independent of the Rails Migration up/down. Rails Migrations are just normal classes, and you can make use of them however you like. For example:
rake db:create_sequence
Choice 2: run your specific migration after you load the schema like this:
rake db:setup
rake db:migrate:up VERSION=20080906120000
Choice 3: create your sequence as seed data, because it's essentially providing data (rather than altering the schema).
db/seeds.rb
Choice 4 and my personal preference: run the migrations up to a known good point, including your sequence, and save that blank database. Change rake db:setup to clone that blank database. This is a bit trickier and it sacrifices some capabilities - having all migrations be reversible, having migrations work on top of multiple database vendors, etc. In my experience these are fine tradeoffs. For example:
rake db:fresh #=> clones the blank database, which you store in version control
All the above suggestions are good. however, I think I found a better solution. basically in your development.rb put
config.active_record.schema_format = :sql
For more info see my answer to this issue -
rake test not copying development postgres db with sequences
Check out the pg_sequencer gem. It manages Pg sequences for you as you wish. The one flaw that I can see right now is that it doesn't play nicely with db/schema.rb -- Rails will generate a CREATE SEQUENCE for your tables with a serial field, and pg_sequencer will also generate a sequence itself. (Working to fix that.)

Resources