Archives (February 2009)



ActiveRecord : Building a Rails application based a legacy database



Written by Anthony Heukmes on Fri Feb 20 15:45:30 UTC 2009

3 comments



In a perfect world, a new data schema is created with a new Rails application. The database evolves with the application and will respect all the ActiveRecord conventions.
It is the ideal case because no configuration is required and you can fully benefit of migrations.
The development speed reaches his maximum.

But legacy databases are everywhere in professional environments.
A big Oracle schema which doesn't respect any ActiveRecord convention and that you cannot modify because other applications are already based on it.
The only thing you can do is create views in your schema and it is often very useful. But it's not enough.

Does that mean you have to forget about Rails and come back to Java development? Fortunately, the answer is no! :-)

As you already know, a schema is "compatible" with ActiveRecord if he follows a few conventions. So the name of the table must be the pluralized name of the model (User -> Users)
and your primary key must be an auto-incremented value called ID.
The MUST verb is however not right here. If you follow the conventions, you will not have to configure your model, the mapping between your Ruby object and your table will be done automatically. But if the conventions are not respected, you'll always have the possibility to configure the mapping yourself.

Let's take the following schema :



It clearly doesn't follow the ActiveRecord conventions. The name of the "my_users" table should be "users", and the primary key should be "id" instead of "my_pk."

I'm working with an Oracle database that doesn't support auto incrementation like MySQL does. To achieve the same goal, I had to create a sequence named "my_users_autoi".

My User.rb class looks like this :


class User < ActiveRecord::Base

set_table_name 'my_users'
set_primary_key 'my_pk'
set_sequence_name 'my_users_autoi'

end


As you can see, there is no magic here. You can now manipulate your model, all CRUD operations are available. And if you try to create a new user, you'll notify that the db sequence is used to assign the primary key.

A user can write articles. So there is a one-to-many association between the two entities. The article class respects the two previous conventions but the name of the foreign key is not correct. It should be user_id. We have to configure our model and add the relationship in the User class :


class Article < ActiveRecord::Base

belongs_to :user, :foreign_key => 'by_user'

end

class User < ActiveRecord::Base
...
has_many :articles, :foreign_key => 'by_user'
end


You can then start manipulating your data :

((
usr = User.create(:pseudo => 'antho', :email => 'ahe@me.com')
Article.create(:title => 'My first article', :user => usr, :creation_date => Date.today)
usr.articles.first.title # => 'My first article'
))

And voilaaa!

The Ranking table is however a little more problematic. Users can rate articles, giving them a note between 1 & 5.
The primary key of this table is composite : it is based on BY_USER and FOR_ARTICLE.
ActiveRecord doesn't support composite primary keys but fortunately there is a library supporting this feature.
Install it following the instructions on the website of his author.

When it's done, create the Ranking class and update your previous classes to reflect this new association :


class Ranking < ActiveRecord::Base

set_table_name 'ranking'
set_primary_keys :by_user, :for_article

belongs_to :user
belongs_to :article

end

class User < ActiveRecord::Base

set_table_name 'my_users'
set_primary_key 'my_pk'
set_sequence_name 'my_users_autoi'

has_many :articles, :foreign_key => 'by_user'
has_many :rankings, :foreign_key => 'by_user'

end

class Article < ActiveRecord::Base

set_sequence_name 'articles_autoi'

belongs_to :user, :foreign_key => 'by_user'
has_many :rankings, :foreign_key => 'for_article'

end


Users can now rate your articles :


rk = Ranking.new
rk.rank = 5
rk.by_user = usr.my_pk
rk.for_article = usr.articles.first.id
rk.save


Don't miss the fact that you have to specify explicitly the primary key (user.my_pk & article.id).

And that's it! I think you can now affirm that a Rails application can be easily created on a legacy database!

Ruby on Rails plugin : manage the titles of your pages very easily!



Written by Anthony Heukmes on Tue Feb 17 20:35:01 UTC 2009

0 comment



EasyTitles is a Ruby on Rails plugin that allows you to easily manage the titles of your pages.
Instead of creating @title variables inside your controllers & views, EasyTitles gives you the possiblity to centralize your titles in YAML files.
This plugin also supports internationalization (I18n) if you use a version of Rails >= 2.2.

The big advantage is that all titles are centralized in one place, making them easy to manage.

Let's say that you have a REST "Articles" controller (with basic CRUD methods), the only one thing you have to do is to create a YAML file respecting the following format :


articles:
index: "Listing articles"
show: "Article details"
new: "New article'"
edit: "Edit article"


You can then add a call to the easy_title helper method in the title tag of your layout :


<title><%= easy_title %></title>


This method will determine the title to display in function of the current controller name & action name.
So if you are on the /articles/show page, the title "Article details" will be displayed.

EasyTitles also allows you to set default titles :


default: "This title will be displayed for any controller/action without a defined title"
articles:
default: "This title will be displayed for articles methods without a defined title"
index: 'Listing articles'
show: 'Article details'
new: 'New article'
edit: 'Edit article'


Installation





  1. script/plugin install git://github.com/ahe/easytitles.git

  2. Create a titles folder in your config folder (RAILS_ROOT/config/titles).

  3. If you are not using I18n (internationalization) create a all.yml file in your titles folder.

  4. Otherwise, create a yml file for each locale (en.yml, fr.yml, …) in your titles folder.

  5. Put all your titles in the yml file(s) while respecting the above format.

  6. Add the easy_title call in your title tag : <title><%= easy_title %></title>