How do others set up foreign key relationships in migrations - ruby-on-rails

I'm developing some things in Ruby on Rails, and I've currently got several models with relationships between them. Now, the models specify the relations, so I know that RoR will enforce integrity, but what about at the DB level ?
Do other people set up foreign key relationships in DB tables ? and if so, how ?, there doesn't seem to be any way to setup/destroy a db relationship in a migration (maybe using raw SQL)
Thanks
Paul.

Here's a guide on how to do it:
http://seb.box.re/2006/7/29/foreign-key-and-rails-migration
There is also a plugin for this here:
http://github.com/harukizaemon/foreign_key_migrations/tree/master
However, Rails does not easily support foreign keys in migrations for a reason. Basically they're not really necessary when using ActiveRecord.
Here's a good explanation of why they are not necessary and their usage is discouraged in rails: http://www.motionstandingstill.com/i-dont-use-foreign-key-constraints-with-rails/2008-10-17/
Opinions differ on this subject. There's a good discussion here: http://forum.softiesonrails.com/forums/3/topics/138

There isn't a way to do it from the migration short of using SQL, which means that:
It's DB-specific
You have to use SQL
The first isn't really that big a deal (how often do you switch databases on a project anyway?), and the second is simply a fact of life. So, use them if you want.

Incidentally these things should always be set up at the database level. There are other ways to access and change data in the database besides the application. You should never set these types of rules in the application unless you want useless data. All things that touch on data integrity must be at the database level even if you have to (GASP) use SQL.

Related

Where to place sql queries in rails?

I have started a rails project on top of a legacy database. Standard practices required to use an ORM, like assigning ID field to each table, haven't been followed. So, I will not be creating all the models matching all the table. I need to run queries joining multiple tables using numerous conditions. I will mostly be using Model.find_by_sql or Model.connection.select_all methods. Where should I put these queries? Should I stash these in one of the models I have created that is involved in the query?
What's the standard practice for such a situation?
As much as possible, you still want to insulate the rest of your application from the details of the database by putting your queries and whatnot into the model layer. So yes, "stashing" in the right model object relevant to what you're trying to do seems like the right thing.
Are you allowed to change the schema of the database? If so, you may want to use migrations to slowly make your database look more like a standard ActiveRecord backing store.
You may also want to look into alternatives to ActiveRecord such as Sequel.
It is good idea to place the sql queries under sql folder under db. You need to create the sql folder.

Rails3 and legacy database

I'm wondering if working with rails (3) is a good idea when a huge/ugly legacy database is already there (Oracle, SQLServer).
I only have experience with ActiveRecord, is there another ORM more suitable for that kind of job?
Cheers
ActiveRecord can still do the job - for example there are directives that can be applied within your model that make non-conventional table names, primary key names (multi-column PKs, if you have them, used to require some additional work, not sure how true that is in AR3).
For both Oracle and SQL Server you're going to need to get the relevant DB adapters; I don't think either is bundled with AR.
A lot of legacy DB Rails work only needs read-only access - if that's the case - and you can get access to do so - then you may find that defining views that are more "AR-friendly" and referencing those through your models may make life easier. If update is going to be necessary then either a useable primary key will be needed or you'll have to consider dropping down to building and executing custom SQL, something that's fully supported in AR for occasions when the abstractions can't cope.

How to create a user customizable database (like Zoho creator) in Rails?

I'm learning Rails, and the target of my experiments is to realize something similar to Zoho Creator, Flexlist or Mytaskhelper, i.e. an app where the user can create his own database schema and views. What's the best strategy to pursue this?
I saw something about the Entity-Attribute-Value (EAV) but I'm not sure whether it's the best strategy or if there is some support in Rails for it.
If there was any tutorial in Rails about a similar project it would be great.
Probably it's not the easiest star for learning a new language and framework, but it would be something I really plan to do since a long time.
Your best bet will be MongoDB. It is easy to learn (because the query language is JavaScript) and it provides a schema-less data store. I would create a document for each form that defines the structure of the form. Then, whenever a user submits the data, you can put the data into a generic structure and store it in a collection based on the name of the form. In MongoDB collections are like tables, but you can create them on the fly. You can also create indexes on the fly to speed searches.
The problem you are trying to solve is one of the primary use cases for document oriented databases which MongoDB is. There are several other document oriented databases out there, but in my opinion MongoDB has the best API at the moment.
Give the MongoDB Ruby tutorial a read and I am sure you will want to give it a try.
Do NOT use a relational database to do this. Creating tables on the fly will be miserable and is a security hazard, not just for your system, but for the data of your users as well. You can avoid creating tables on the fly by creating a complex schema that tracks the form structures and each field type would require its own table. Rails makes this less painful with polymorphic associations, but it definitely is not pretty.
I think it's not exactly what you want, but this http://github.com/LeonB/has_magic_columns_fork but apparently this does something similar and you may get some idea to get started.
Using a document store like mongodb or couchdb would be the best way forward, as they are schema-less.
It should be possible to generate database tables by sending DDL-statements directly to the server or by dynamical generating a migration. Then you can generate the corresponding ActiveRecord models using Class.new(ActiveRecord::Base) do ... end. In principle this should work, but it has to be done with some care. But this definitely no job for a beginner.
A second solution could be to use MongoMapper and MongoDB. My idea is to use a collection to store the rows of your table and since MongoDB is schema less you can simply add attributes.
Using EntryAttributeValue allows you to store any schema data in a set amount of tables, however the performance implications and maintenance issues this creates may very well not be worth it.
Alternately you could store your data in XML and generate an XML schema to validate against.
All "generic" solutions will have issues with foreign keys or other constraints, uless you do all of that validation in memory before storage.

Problems using a legacy database with a new rails application

What are the usual problems / stumbling blocks / issues / drawbacks when using a legacy database with a new rails application?
We have to decide between using an old database or writing migration scripts to bring data from old database to new database following rails conventions. What would you suggest?
Table naming was one that got me for a while. The trick was to use this in your models:
set_table_name 'old_table_name'
set_primary_key 'old_key_column'
That way you can use whatever model name you want while linking to any table you want.
1) Typically the first issue is the database schema design has composite primary keys (multi column keys), where Rails (or at least ActiveRecord) wants primary keys named "id". Many good data models don't use surrogate keys, they use natural keys, so they cannot avoid composite keys. In practice, when designing a new database for an ORM, it is more practical to use surrogate keys named "id", but enforce data integrity by always including an alternate key constraint / index on the natural key.
2) Table naming that uses plural vs singular (Rails wants plural to map to its domain objects. With many databases this can be overcome easily with synonyms.
Those are the two issues I've run into with Rails and other MVC frameworks, but some have changed in the past couple of years and provided alternatives to simplistic nonsense. It is expensive to change a legacy database, and enforcing a naming convention is a big mistake which I believe has been learned now.

Rails with DB2 and multiple schemas

I have a 'legacy' DB2 database that has many other applications and users. Trying to experiment with a rails app. Got everything working great with the ibm_db driver.
Problem is that I have some tables like schema1.products, schema1.sales and other tables like schema2.employees and schema2.payroll.
In the ibm_db adapter connection, I specify a schema, like schema1 or schema2, and I can work within that one schema, but I need to be able to easily (and transparently) reference both schemas basically interchangeably. I don't want to break the other apps, and the SQL I would normally write against DB2 doesn't have any of these restrictions (schemas can be mixed in SQL against DB2 without any trouble at all).
I would like to just specify table names as "schema1.products" for example and be done with it, but that doesn't seem to jive with the "rails way" of going about it.
Suggestions?
Schemas in DB2 are a very handy way to provide separate namespace to different applications. For example, you can separate all database objects for an application called "recruiting" from say application called "payroll". You can have objects (tables, views, procedures etc.) with the same name reside in multiple schemas and not colide with one another. Having your application set a schema is a handy way for it to say "hey, I am a payroll and I only want to work with my objects". So, what happens when you want to work with objects owned by another application? Well, in traditional procedural programming languages your application code would explicitly specify the schema when referencing an object in another schema or you would just do a SET CURRENT SCHEMA to switch to another schema. The problem with ORMs like ActiveRecord in Ruby on Rails is that you are not supposed to use SQL i.e. you don't have a good "Rails way" to specify schema when referencing an object. You can use find_by_sql and qualify your objects in the SQL statement but this is not what RoR people will consider to be good Rails.
You can fix things on the DB2 side. You can define a view per table in the "foreign" schema but you will have to take care to name the view so that it does not colide with what you already have in your primary schema. And, when you do that, you will undoubtedly create names that are not true Rails names.
Rails people are very proud of the "Rails way". It makes it very easy to create new applications. Rails is really awesome in this space. However, when it comes to integration with what is already out there Rails ... how do we say it ... sucks. I suggest you will have to accept to do things that are not the best examples of the Rails Way if you want to work with existing database structures.
How do i work with two different databases in rails with active records?

Resources