Rails test with triggers - ruby-on-rails

I noticed that Rails creates triggers in the development db but not the test db since it creates the test db from schema.rb instead of running migrations. I have a trigger (as a migration) and need to test that it does the right thing, how can I do that? I tried adding the trigger manually to the test db but that didn't work.

By default rails sets up the test database using the database independant schema.rb, which doesn't understand stuff like triggers.
If you change config.active_record_schema_format to :sql then rails will instead dump the raw SQL that represents the development database's structure and use that to recreate the test database. This dump is placed in development.sql, which is then used instead of schema.rb
This dump is done using the command line tools that your db provides and so will respect features like triggers that active record isn't aware of

If you do prefer Ruby dumps to SQL dumps you might give this gem a try:
https://github.com/jovoto-team/trackless_triggers
It supports dumping triggers and functions for mysql.

Related

Is there any chance of testing the PostgreSQL database in this scenario without duplicating the database in the development environment?

“I have a Rails application with PostgreSQL database. My database contains 1000 records in it.
I have written a rake task which will manipulate the records in the database.
If the rake task went wrong i want to revert back the changes to the original in the database.
is there any chance of testing the database in this scenario without duplicating the database in the development environment ?”
In Rails itself having the feature sandbox
If you wish to test out some code without changing any data, you can do that by invoking rails console --sandbox.
bin/rails console --sandbox
Loading development environment in sandbox
Any modifications you make will be rolled back on exit
irb(main):001:0>
You can paste your ruby code here and can see the changes you wanted to see. while closing this console, All your changes will be reverted back(running as a transactional)
For more informations you can refer this link
http://edgeguides.rubyonrails.org/command_line.html#rails-console
you can duplicate a database in same env.
create database test with template original_db;
Will create cop of existing db, on which you can run your tests, specifying test instead of original db name in connections string

How can I convert all migration files into a single file in Rails?

I have been developing a project in Ruby on Rails. During the development I have generated tons of migration files for my project. Sometimes I have added and deleted columns from different tables.
Is there a way that I could consolidate all the migrations from multiple files into a single file?
TL;DR
What you need isn't a consolidated set of migrations; it's a single schema file and an optional seeds.rb file. Rails generally maintains the schema automagically when you run migrations, so you already have most of what you should need with the possible exception of seed data as described below.
Use the Schema, Not Migrations
In general, you shouldn't be maintaining a large pool of migrations. Instead, you should periodically clear out your migrations, and use schema.rb or schema.sql to (re)create a database. The Rails guides specifically state:
There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema...Because schema dumps are the authoritative source for your database schema, it is strongly recommended that you check them into source control.
You should therefore be using bin/rails db:schema:load rather than running migrations, or run the associated Rake task on older versions of Rails.
Data Migrations
While you can use migrations to fix or munge data related to a recent schema change, data migrations (if used at all) should be temporary artifacts. Data migrations are almost never idempotent, so you shouldn't be maintaining data migrations long-term. The guide says:
Some people use migrations to add data to the database...However, Rails has a 'seeds' feature that should be used for seeding a database with initial data. It's a really simple feature: just fill up db/seeds.rb with some Ruby code, and run rake db:seed...This is generally a much cleaner way to set up the database of a blank application.
Database seed data should be loaded with bin/rails db:seed (or the associated Rake task) rather than maintaining the data in migrations.
There is a gem that purports to do exactly what you describe in the question - check out Squasher.
From the README:
"Squasher compresses old migrations in a Rails application. ... Squasher removes all the migrations and creates a single migration with the final database state of the specified date (the new migration will look like a schema)."
You'll have to do the merge manually.
But if you want only a single file, there is db/schema.rb. It contains a snapshot of current database schema. You can load it directly in database if you want.

What is the use of the Schema.rb file?

What exactly is the use of the Schema.rb file?
It is a generated file when you run your migrations. To the best of my knowledge it has two uses:
Your database schema is in one place and can be viewed and reviewed.
You can load your database in one shot by use rake db:schema:load instead of having to walk through your migrations
This file is reproduced every time you execute a migration. It reproduces the entire schema of your database. It is also used by certain commands in migration in Rails to avoid redoing all the migrations one by one (in the case of a migration reset for instance).
It is also the only place when you can see all your tables at once for the reference of columns. But I suggest you to use the gem annotate in order to document your models with all column names. It's easier to work like this than having to go to schema.rb everytime you want details about the DB structure of your model.
One good usage of schema.rb is whenever we run rake test, it prepares the test database instantly using schema.rb(without running the migrations).

Rails - authoritative source for your database schema?

I have Rails app, and every once in a while, when I bring new developer onboard they exclaim that they should be able to produce the current DB schema in their dev environment by running the whole history of the migrations. I personally don't think that migrations is the authoritative source for your schema. Right now what we do is load a production copy of the DB, with the current schema, onto the dev machine. And, from there, the schema can be maintained via incremental migrations.
So my question are:
What is the authoritative source of your schema on a Rails project?
What is now considered the best-practice way to maintain your DB schema?
I do not consider migrations to be the authoritative source for your schema. Migrations are extremely powerful but optional. Some developers use alternative workflows especially in environments where DBA's insist on strong referential integrity and DBMS-enforced constraints. I suggest looking at the official RoR Guide on Migrations for more information. The db/schema.db (or db/{env}_structure.sql) file is the authoritative source for your schema. Many developers will purge old migrations as projects get older so running each migration will not necessarily produce a working database. It also takes a long time to run through a hundreds of migrations. Rails uses schema.db (or the sql dump file) to build the test database and of course when running rake db:setup which is the recommended way of creating a new database for your application.
Bottom like is that rake db:setup should always produce a working database regardless of migrations. Developers can use this to create new environments and Rails uses this to run your tests.
http://guides.rubyonrails.org/migrations.html#schema-dumps-and-source-control
Normally, running the succession of all migrations should produce your actual DB schema (if it's not the case, then you didn't use your migrations correctly*).
Another way of doing is to copy over the schema.rb (created/updated when you migrate), which is used by rake db:setup and should produce an exact copy of the schema you have in production (unless, again, you didn't use migrations correctly*).
Then, if you need "sample data", you can insert it using the db/seeds.rb file, which contains ruby code that can access your models, and thus create and persist new entities & so on...
*: There are cases where you can't put all your database changes in migrations in a "usual" way (it is uncommon and should be avoided if possible)... These should be included in migrations however (in plain SQL execution statements), or the changes would need to be made manually on the dev DB as well... And then using a snapshot of prod. is sometimes more convenient. But again, I would discourage doing so.

Ruby on Rails and db:fixtures:load - can it ignore some models?

I have two databases in use in a Ruby on Rails application; one is the database for the application while the second is an independent database over which Rails is not given control.
Problem is when loading fixtures into the dev, it tries to run DELETE statements on the tables in the independent database from the connection to the dev database, which obviously errors out.
I don't want Rails to try to do ANYTHING but read the independent database - I especially don't want it trying to delete tables.
Is there a simple way to tell Rails to ignore the models for the second database when loading fixtures?
UPDATE: To clarify, Rails seems to think the tables from the independent database are part of the development connection, though I have specified the correct connection in the model class using establish_connection. As another note, all model classes work precisely as desired from script/console.
rake db:fixtures:load RAILS_ENV=testing
will do the job for database configured as testing in your database.yml
I think you might also be able to accomplish this by adding all the tables in the independent database to ActiveRecord::SchemaDumper.ignore_tables in environment.rb, like so:
ActiveRecord::SchemaDumper.ignore_tables = ['independent_db_table1', 'independent_db_table2']
Okay...my issue was that I used the script/generate to create the models from the secondary database, which also created fixture, schema, test, and migrations files. I had removed the schema, test, and migrations files, but did not remove the generated fixtures (they were empty files) as I did not think it had created any.
After removing all files (including the models) from the secondary database and re-running the migrations for the dev db, I added back only the model files and the database in databases.yml from the secondary db, which solved the issue.
I still can't explain why Rails' rake tasks were looking in the wrong database and I am a little disappointed with rails' addition of the schema_migrations table in the secondary database, which it obviously does not need.
However, it works now.
Delete the model_name.yml file in your test/fixtures directory and Rails will not try to delete these tables.
Better yet, delete all your *.yml files and stop using fixtures entirely.

Resources