Thursday, April 24, 2008

Some chewable Ruby

1. An anonymous class is a Singleton class which when created sits between an instance and it's metadata. Basically it takes over the klass relationship on the instance end and relates to the metadata through the super.
2. A class is also an instance in Ruby. So, a class instance variable goes into the Singleton between a Class Definition and the Class Metadata. Therefore, it is visible only to the methods in Class Metadata or in simpler words, only to that class methods of which it is the instance.
3. Instance methods belong in the Class definition and class methods in the Class metadata.
4. The metadata class can be found by following the klass property.

The cute Ruby Class Instance Variable and the Module mama

A pretty decent tutorial to clear out all newbie doubts in the ruby inheritance world and the great service from Module to hold it all together.

Good read for anyone wishing to build a plugin and wanting to get hands dirty.

http://railstips.org/2006/11/18/class-and-instance-variables-in-ruby

Tuesday, April 22, 2008

To make redhillonrails_core work on Oracle

To get the foreign keys. Implementation is your choice.

def foreign_keys(table_name, name = nil)

foreign_keys = []
p table_name
result = select_all(<<-SQL, name)
SELECT UNIQUE CONSTRAINTS.CONSTRAINT_NAME as constraint_name,
SINK.TABLE_NAME as from_table_name,
SINK.COLUMN_NAME as column_name,
SOURCE.TABLE_NAME as ref_table_name,
SOURCE.COLUMN_NAME as ref_col_name,
CONSTRAINTS.DELETE_RULE as del_rule,
CONSTRAINTS.DEFERRABLE as deferrable,
CONSTRAINTS.OWNER as owner,
SINK.OWNER as from_table_owner,
SOURCE.OWNER as ref_table_owner
FROM ALL_CONSTRAINTS CONSTRAINTS, ALL_CONS_COLUMNS SOURCE, ALL_CONS_COLUMNS SINK
WHERE CONSTRAINTS.R_CONSTRAINT_NAME=SOURCE.CONSTRAINT_NAME
AND CONSTRAINTS.CONSTRAINT_NAME=SINK.CONSTRAINT_NAME
AND CONSTRAINTS.OWNER=SINK.OWNER
AND CONSTRAINTS.OWNER = SOURCE.OWNER
AND CONSTRAINTS.TABLE_NAME=SINK.TABLE_NAME
AND SOURCE.POSITION=SINK.POSITION
AND CONSTRAINTS.TABLE_NAME = UPPER('#{table_name}')
SQL
result.each do |row|
p name = row['constraint_name']
p from_table_name = row['from_table_name']
p column_names = row['column_name']
p references_table_name = row['ref_table_name']
p references_column_names = row['ref_col_name']
p on_delete = on_delete.downcase.gsub(' ', '_').to_sym if ['CASCADE','SET NULL'].index(row['del_rule'])
foreign_keys << ForeignKeyDefinition.new
(name,

from_table_name,
column_names.split(','),
references_table_name,
references_column_names.split(','),

nil,on_delete,nil)
end
p foreign_keys.to_s
foreign_keys
# []
end

DAG, versioning and an opportunity

Got a new task at hand.
Suppose I have evolving entities E1, E2 ... En in my system, each having assets from a group of A1, A2 ... An. Each of these entities can mutate but the historical relationships with the assets need to be preserved.
Each entity's assets can be determined by the has_many relationships.
E.g. E1 has a has_many relationship with A1, A2
Thus, when E1 1.0 mutated into E1 1.1, all related A1, A2 assets are copied over for E1 1.1
After copying over the inheritance, one can can add/subtract/update the assets.
E.g. E1 1.0 had attached A1 1.0 but had no item from the asset group A2. Now E1 1.1 was created, with parent as E1 1.0, therefore E1 1.1 now also inherits A1 1.0. Now, one should be able to add any available item from asset group A2, say A2 1.4
In other words, each of the entities (assets can also be generically be categorized as an entity for versioning), can be represented on a DAG or Directed Acyclic Graph. The DAG is how the entity evolves.
Lets see how I am able to deal with this situation.
Will I write something like act_as_dag? If I can that will be quite an achievement...

Monday, April 21, 2008

Enter redhillonrails_core

A great plugin to support FK/indexes etc in Rails migrations. Stock migrations do not really appeal in the referential constraints area. I installed this plugin to find out that there is no adapter for Oracle. It supports Postgres and mySQL but uses a generic adapter for Oracle. And the generic adapter is no good. It just fills the gap so that the plugin does not error when using with Oracle but essentially rake db:schema:dump does not do any FK dumping.
I pointed out at rubyforge but got to know that what I found out was true and there were no plans to support Oracle in the near future.
So, I decided to extend the Adapter myself. Not a very tough task. Just had to query Oracle and find out the FK definitions. Will write the query or perhaps make it into a plugin sometime when I am done with testing.

Friday, April 18, 2008

Searching for a better migration

Started scouring the net for a decent project path which will enable me to implement migrations in the middle of a development lifecycle and found that there were some great plugins in the Rails world but none of them suit my purpose in a sufficient way.
So, what was I looking for.
I was looking for
1) A way I could start using Migrations in the project. Which primarily leads me to decide on how migrations could be managed. Working on a large scale product, I thought that using stock migrations would not be helpful. Especially when database changes become decentralized and then we start having problems with migrations not working because their numbers do not match. (Of course one can argue saying that we could have a hook at source control to handle that but remember that is an extra effort). Then of course there is this ever looming problem of migration decay. For the uninitiated, migration decay aptly worded simply means that running migrations of a fresh DB could fail because the lower migrations run into problems as the models have evolved. The earlier migrations expect a different model and boom! Very typical when data migrations are mixed with schema migrations. Intuitively, I thought that it would not be a great idea to have to run a lot of migration files to get the instance to speed.
So, what was my other option that generating migrations for every DB update?
I think the best bet is to use schema.rb
Schema.rb generated when you run a rake task, can contain the entire schema dump.
This was attractive and sweet. So the intention was to have a single source controlled file which makes me feel safe.

Coming soon
2) How to handle foreign keys/views
3) Was there a better way to make life (more) hassle free?