Archive for June, 2006

Ruby On Rails Controller Path

With Ruby on Rails, you can redirect to or link to an action in different controller. For example, to redirect to the login action in the account controller you can use the following from withing a controller in you rails application:

redirect_to :controller => 'account', :action => 'login'

When this redirect statement is executed you application will redirect to a URL like the following:

http://localhost:3000/myapp/account/login

The controller value is like a fragment of URL and can refer to a controller relative to your current controller location or can be absolute to you rails application. Because you can place controllers in their own directories under the app/controllers you can easily imagine having an admin/user_controller. In this case, from the user controller you can refer to another controller that is at the root level by the following:

redirect_to :controller => '../account', :action => 'login'

The controller portion of the redirect to, the ‘../account’ part, is relative to your current controller. To refer to a controller with an absolute path you can do the following:

redirect_to :controller => '/account', :action => 'login'

The controller portion of a redirect is really just a path which can be relative to your current controller or absolute to your rails application and the rails routing will do the right thing for you. This same logic applies to the link_to function.

Technorati Tags: , , ,

Belated Spring Cleaning

I was reorganizing and cleaning my technical bookshelf earlier today. I have a whole bunch of books that I don’t use and are just taking space. I want to donate some of these books to my local library, maybe up and coming techies will get some use out of them. Some of these books are a little dated but others are just not useful in day to day software development. Now that I am into Ruby, Python, and Groovy I just don’t have much room in my bookshelf for Perl books. I have a whole pile of Perl books that I am going to toss out, books like Perl Cookbook, Programming Perl, and Advanced Perl Programming. The only Perl book that I am thinking of keeping is Learning Perl. I also don’t have space for antiquated web frameworks so out goes Programming Jakarta Struts, Professional Struts Applications, Enterprise JavaBeans Component Architecture, and Enterprise JavaBeans.

I think these books will be replaced with up coming Groovy titles and maybe the second edition of Agile Web Development with Rails.

Technorati Tags: , , , ,

Query Managed Auto Increment

Different database vendors allow you to auto increment an integer primary key in different ways. I thought that I could manage to increment the primary key from within the same insert statement. Given the following table:

CREATE TABLE temps (
   id INT NOT NULL,
   name VARCHAR(10) NOT NULL,
   PRIMARY KEY (id)
);

I thought could create a single insert statement that also managed to auto increment the id primary key. I thought I could do something like:

INSERT INTO temps VALUES(
   (SELECT max(t.id)+1 FROM
      (SELECT id FROM temps UNION SELECT 0)
   t),
'juixe');

When I run the above insert statement using MySQL 4.1.15 I get an error that reads, “You can’t specify target table ‘temps’ for update in FROM clause.”

Using Microsoft SQL Server 2005 Express I get an error that reads, “Subqueries are not allowed in this context. Only scalar expressions are allowed.” This is most unfortunate because subqueries are really powerful.

I had better luck on Oracle Database 10g Express Edition where I could run what I call Query Managed Auto Increment statement. On Oracle 10g EX I was able to run the following Query Managed Auto Increment statement with a minor modification:

INSERT INTO temps VALUES(
   (SELECT max(t.id)+1 FROM
      (SELECT id FROM temps UNION SELECT 0 from user_tables)
   t),
'techknow');

What doesn’t work well in Oracle is that you can’t run a select statement without a table name. On Oracle you can’t run the following statement: select 0. Query Managed Auto Increment works in Oracle but you would need default to a table that has at least one record, such as the user_tables table.

Just for completeness I tried PostgreSQL 8.1.4. PostgreSQL supports static select statements, select statements without the from clause and return a constant value. Because PostgreSQL supports static select statements I am guaranteed that the following will return at least one row of ids even if the table is empty:

SELECT id FROM temps UNION SELECT 0;

Adding one to the max id returns the next primary key id, which I use in the insert statement. Once again here is the working SQL (in PostgreSQL) that manages the primary key and automatically increments the id to the next available integer value.

INSERT INTO temps VALUES(
   (SELECT max(t.id)+1 FROM
      (SELECT id FROM temps UNION SELECT 0)
   t),
'zenze');

So in conclusion, Query Managed Auto Increment doesn’t exactly work in MySQL because you can’t use a subquery that refers the same table as the insert. SQL Server has the limitation that you can’t even execute a subquery in an insert. And as we have seen Query Managed Auto Increment works on Oracle and PostgreSQL.

Technorati Tags: , , , , , ,

Rails Single Table Inheritance

Ruby on Rails supports Single Table Inheritance. Single Table Inheritance allows you to have one single SQL table, such as an employees table, manage different type of employees like managers and developers. A manager would normally have more responsibilities than a developer and you can separate these additional responsibilities in a different ActiveRecord model class.

Here is another example of Single Table Inheritance that you might find useful. You might have to support a hierarchy of users for you web application, such as User, Editor, and Administrator. An Administrator might have full Create, Read, Update, and Delete (CRUD) access while a User might just have read access. For this hierarchy of users you will need to create a Ruby class for each type and place it in the Rails app/models directory. Here is the base User class:

My Editor class:

And the Administrator class:

Place each of these classes in their own Rails model file under the app/models directory.

To indicate to Ruby on Rails that the users table needs to support Single Table Inheritance you need to add a column named ‘type’ to the users table. Here is my users table definition:

In the column named type you should store the name of the class, the class type, that should be used for each user. To mark an certain user as an admin set his type to ‘Administrator’. By setting a user’s type to ‘Administrator’ you are giving him full administrator privileges as defined in your Administrator model class.

And now, in your controller you can look up all users that are administrators by using the following bit of code:

If you want to look up all known users you can do so by using the User class as in the following snippet of code:

At this point, you would add additional responsibilities to editors and administrators by adding methods to those model classes.

Technorati Tags: , , , ,

« Previous Page