Foreign Key constraints not copying into testdb during rake - ruby-on-rails

Here is one issue which I am unable to debug. While doing an rake db:test:clone_structure, the foreign keys that are not copied from development database to test database. Is there anything that I am missing?

Your problem is that Rails (or ActiveRecord) doesn't understand foreign keys inside the database, nor does it understand CHECK constraints or anything else fancier than a unique index. Rails is generally nice to work with but sometimes there is more attitude than good sense in Rails.
There is Foreigner for adding FK support to ActiveRecord but that doesn't know about Oracle. You might be able to adapt the PostgreSQL support to Oracle but I don't know my way around Oracle so that might not be a good idea. Foreigner also doesn't support CHECK constraints (yet).
The quick solution would be to dump the FKs and CHECKs as raw SQL and pump that SQL into your test and production databases. Then wrap a quick script around that that does a rake db:test:clone_structure followed by the raw SQL FK and CHECK copying.
Sorry that there's no easy way to do this but once you get outside the bounds of what a framework wants to do things get ugly (and the more comprehensive the framework, the uglier things get). A little bit of SQL wrangling wrapped around the usual rake command isn't that nasty though.

Related

Rails : Why shouldn't I directly make changes directly in schema than do migrate

I am using ruby on rails for an application. I am developing it on my local server as of now.
Everytime I need to make a change to the database, I need to create a migration. Why can't I directly make changes in schema.rb itself?
I am allowed to reset the database and reset all values in the tables. I came across a problem where I needed to change date format from "dateTime" to "timestamp". Now there are just too many fields to change. Why can't I just change them in schema.rb?
schema.rb is an automatically generated file and will be dumped from the current state of the database after you ran a migration. Although I strongly discourage it, it is in fact possible to change it manually, then run rake db:schema:load to apply it to the database. However, you will loose all the benefits you get from migrations, and you'd be ignoring the convention.
So, what are the benefits, you ask? Just to name a few:
They can be rolled back when you made a mistake
They make it easier to handle multiple developers on a single project
They provide a place to clean up and move around data before/after applying the change
They give you a history of changes to the database schema
They reduce some of the boilerplate by mapping rails concepts such as polymorphic relationships to simple DSL commands so you don't need to think as much how the columns should be named and typed
First, migrations are easily revertable. Second, with migrations you have history and, more important, order of changing things. Third, you can add additional code to migrations (for example, calculate some value for just added column).
And I'm sure there are more benefits.
Migrations are key to ensuring that your dev, test and prod environments are all identical. If you start mucking around in the database manually dev will very quickly look nothing like prod... In fact, it becomes extremely likely that you will begin doing your development in prod which is a very bad idea!

ActiveRecord and NoSQL

I've been working with Rails for a few years and am very used to ActiveRecord, but have recently landed a task that would benefit from (some) NoSQL data storage.
A small amount of data would be best placed in a NoSQL system, but the bulk would still be in an RDBMS. Every NoSQL wrapper/gem I've looked at, though, seems to necessitate the removal of ActiveRecord from the application.
Is there a suggested method of combining the two technologies?
Not sure what NoSQL service you are looking into, but we have used MongoDB in concert with Postgres for a while now. Helpful hint, they say you need to get rid of ActiveRecord, but in reality, you don't. Most just say that because you end up not setting up your database.yml and/or running rake commands to setup AR DB.
Remember also that Postgres has HStore and JSON datatypes which give similar functionality as NoSQL datastores. Also, if the data you are looking to store outside of your AR DB is not very complex, I would highly recommend looking into Redis.
If you look at the Gemfile.lock of this project, you can see that it uses ActiveRecord with Mongoid.
Even if you use other gems that don't need ActiveRecord, you shouldn't care. If you are using it, you should have a valid reason to do so.

Rails Migration: Pitfalls of using 'execute' to create database constraints

This one's really an off shoot of another question I asked, earlier today.
Basically, it seems like it's not the rails way to have database level constraints (foreign keys) in RoR. At least, they're not natively supported. There's this Foreigner Gem or I could go primitive and use raw SQL through execute in rails migrations.
My question is, are there any pitfalls I need to be aware of when using the execute route. Here are a few that I that I'm aware of:
Writing db seeds/fixtures can get tricky, perhaps impossible for
some cases
Managing db migrations becomes difficult, as the foreign keys would never be dumped in db/schema.rb
Polymorphic foreign keys would not be possible (I don't even know what they are, so, I shouldn't miss those)
Are there any other pitfalls that I should be aware of?

Are there tools for Rails to validate referential integrity of the database?

Applications have bugs or get bugs when updated, some hidden that they get detected months or years later, producing orphaned records, keys pointing nowhere etc. even with proper test suites.
Allthough Rails doesn't enforce referential integrity on the database level - and for some good reasons discussed elsewhere it will stay like that - it would still be nice to have tools that can check if the database is in a consistent state.
Since the models describe what 'should be', wouldn't it be possible that an offline tool validates the integrity of all the data. It could be run regularly, before backing up data or just for the sake of the developers good sleep.
Is there anything like this?
I don't know of such a tool. At least you are aware of the dangers of referential integrity hazards. So why make yourself suffer? Just use foreign key references in the first place, as dportas suggested.
To use it in a migration, add something like this:
execute('ALTER TABLE users ADD FOREIGN KEY (language_id) REFERENCES languages(id)')
to make the language_id column of users reference a valid row in the languages table.
Depending on your DBMS this will even automatically create an index for you. There are also plugins for rails (check out pg_on_rails) which define easy to use alias functions for those tasks.
Checking the integrity only on the backup file is pointless, as the error has already occured then, and your data may be messed up already. (I've been there)
On the other hand, when using foreign key contraints as stated above, every operation which will mess up the integrity will fail.
Think of it as going to the dentist when you feel pain (=having surgery) vs. brushing your teeth ONCE with a magical tooth paste that guarantees that your teeth will be fine for the rest of your life.
Another thing to consider: An error in your application will be much more easier to locate, because and exception will be raised at the code which tries to insert the corrupt data.
So please, use foreign key contraints. You can easily add those statements to your existing database.
How about using the DBMS to enforce RI? You don't need Rails to do that for you.

There is no real 'prepared statement' in rails?

When we use ActiveRecord, we can use:
User.find(:first, :conditions=>["name=?", name])
It looks like ActiveRecord are using 'prepared statement', but after looking into the code, I found ActiveRecord just use String.dup and connection.quote() to adjust the content to build a sql, not like Java.
So, there is no real prepared statment in raiils? And why rails doesn't provide it?
If by prepared statement you mean a piece of SQL that is held in a compiled form for more efficient execution, then you're correct: it's not something implemented in Rails. There are several reasons for this:
Rails is the web framework - it doesn't know or care about databases. By default, Rails uses
ActiveRecord for object-relational mapping. You can change this if you want to - it doesn't have to be a RDBMS even.
ActiveRecord doesn't know about specific database platforms. For that it relies on "adapters", which translate AR's requirements into platform-specific SQL.
Some RDBMSs that have AR adapters support prepared statements (or equivalent) but others don't.
Rails 3.1 (or greater) supports prepared statements. Every new query you make will be added to pool of prepared statement. If you are are using MySql DB it still won't support prepared statement because using prepared statements in MySql reduces the performance compare to without prepared statement. Here is the nice article by Pat Shaughnessy on this.
In many (most?) ways, a DB View is a prepared statement. And it is easy to use views with ActiveRecord. Just declare the view in your DB (I use rake tasks) and then access it via ActiveRecord.
Works great for read-only access to complicated SQL. Saves the DB from many of the steps required to parse/compute SQL.

Resources