Problems using a legacy database with a new rails application - ruby-on-rails

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.

Related

Can a Drupal based website's schema be imported to Rails?

I'm working on a web site that needs to be re-written in Rails. The website was before in Drupal, and there are almost 100,000 records in the database. Now, in Drupal there are tables that do not make any place in Rails in my opinion. For example,
Table name: node_type
It stores information regarding modules in Drupal.
Table name: node
It stores information for node(s) in Drupal.
Table name: semaphore # I've no idea what it is!
Table name: rdf_mapping # No idea
I've not been working with Drupal, so all I want to ask: Is it possible to have a schema for Rails, in which the existing 100,000 records can be imported from Drupal? If so, how? If not so, what are the other options that I'm left with? Or I have to design an entirely new database schema?
Drupal's database schema is not extensively documented for a reason... it's considered implementation details, is not a public API and should not be accessed directly, especially by outside application.
It is also very hard to document because for a given site, any enabled module can add its own tables and alter existing ones (usually adding columns). Plus you have module like Fields (part of Drupal core) that create tables dynamically depending on defined content types.
For a RoR developer, the Drupal schema will probably look weird and be uncomfortable to work with. I would follow suggestion from others, create a new schema for your new application and create a migration script to get the data from the old Drupal database to your new database. I don't knwon about RoR, but try to find a good data migration that allows replay, updates and rollback, etc. You will probably have to migrate the data multiple times to fixes bugs in the process.
Well, I don't have straight forward answers, but I have some ideas what I would do simply to not make so much changes in the database, or as per the comment you can write down an sql script to migrate the data according to the rails schema like types for each tables. Now, I am just intended here to share my thoughts, but I believe there might be more explicit solutions and this is do-able in many ways, may be you need some customizations(?) overriding the default conventions. According to my thoughts, you can try the following things.
Generated Related model skipping migrations
Define tables explicitly to each models like the following snippets:
class Semaphore < ActiveRecord::Base
self.table_name = "semaphore"
end
You have to define foreign keys and primary keys explicitly for both record id and associations.
You have generate time stamp or you can explicitly avoid that like the following ways
ActiveRecord::Base.record_timestamps = false
These are basic things I can see is important.

Rails - How to create database tables from models (I have no migration scripts)

I'm a newbie in rails and its a great platform.
I created an application but removed all the migration scripts.
I want to create the database with the tables from my existed models.
I can't find it on the net and I'm sure that might be an option to do that like any other platform (java hibernate, etc)
the command rails generate... only create the table without columns but I have columns in the existed models. so how can I do that?
Thanks!
If you've accidentally scrubbed your models and don't have any migrations, you can still generate a db/schema.rb file by running rake db:migrate and using that instead. It should reflect the current state of your database no matter what you've done to it.
If you create a migration with the important parts of this in it, as you'll notice the format is very similar, you will be able to replicate that configuration on other systems.
This is a bit of a heavy-handed way to do it, though. Each model should have its associated migration. Generally these are never deleted and only modified if strictly necessary, preserving a history of how the schema evolved into its final state.
If I understand your question correctly, there really isn't a way to construct your database tables from your ActiveRecord model classes - it's best to think of ActiveRecord models as more of a mapping between different flavors of relational databases and Ruby objects. In other words, ActiveRecord models abstract away the details of a database in order to become database-independent. They make your database data more easily accessible in Ruby. In doing so, they don't have the power to construct your tables. Think of them as very pretty getters and setters rather than a binding to a database.
This is exactly why migrations exist - they contain the database-specific stuff. They essentially contain the "other half" of your model definition - most of the application level stuff (like relations, which don't exist in, say, MySQL, right? They are an ActiveRecord convention) is defined on your model, but, for example, if you want to have a string on your Foo model, you define that in your migration, and the appropriate getters and setters will be available on your model for you to play with this string.
tl;dr: you need your migrations. The fact that they exist in Rails is an intentional design decision to separate the Ruby half of the models from the database half.

DataMapper with legacy DB schema. Primary key via sequences table

UPDATE: I wrote a Sequence property type for DataMapper in the end. Take and use at your own risk ;) https://gist.github.com/959059
We're moving a large, already in production PHP web application to Ruby on Rails. Our schema is far from compatible with ActiveRecord's defaults, and it's too large to simply migrate the schema, so I've ditched ActiveRecord and started using DataMapper, which allows us to hide the schema differences more easily. This is working well with some read-only tests I've done.
Now, one of the biggest incompatibilities with our schema is that we use ADODB and generate primary keys prior to the insert, using a sequences table (this is a common pattern), instead of with auto_increment.
Is there a way to tell DataMapper to generate IDs in the same way? I don't see mention of it in the docs.
We can't really switch the tables to use auto_increment because the size of the application means we're actually running a hybrid Rails/PHP setup with some proxying and session sharing so we can progressively migrate across, therefore the PHP application needs to keep working with the schema as-is (or with only minor changes).
I should really have posted that edit as an answer:
I wrote a Sequence property type for DataMapper in the end. Take and use at your own risk ;) https://gist.github.com/959059

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?

How do others set up foreign key relationships in migrations

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.

Resources