ActiveRecord : Construire une application Rails basée sur un schéma existant



Ecrit par Anthony Heukmes le 20 février 2009 15:45

2 commentaires



Dans le meilleur des mondes, le développement d'une application Ruby on Rails coïncide avec la création d'un nouveau schéma. La base de données évolue en même temps que l'application et elle respectera donc les conventions d'ActiveRecord.
Il s'agit du cas idéal car vous n'avez aucune configuration à effectuer pour vos modèles et vous pouvez pleinement profiter des migrations. La vitesse de développement est donc à son maximum.

Mais dans le milieu professionnel, les bases de données « legacy » sont omniprésentes.
Un schéma Oracle imposant qui ne respecte aucune de nos conventions et que vous ne pouvez pas modifier car d'autres applications se basent déjà sur lui.
La seule chose que vous pouvez faire c'est créer des vues dans votre schéma et cela s'avère souvent très utile. Mais ça ne suffit pas.
Cela signifie-t-il que Rails ne conviendra pas pour ce projet et que vous allez devoir repasser au développement Java? Heureusement pour nous, la réponse est non! :-)

Comme vous le savez tous, pour qu'un schéma de données soit "compatible" avec ActiveRecord, il doit respecter certaines conventions. Ainsi, le nom d'une table doit être le nom du modèle au pluriel (User -> Users) et votre clé primaire doit être une valeur numérique auto-incrémentée nommée ID.
Le verbe DOIT n'est cependant pas correct. Si ces conventions sont respectées vous n'aurez pas à configurer vos modèles, le mapping entre votre objet Ruby et votre table en base de données sera effectué automatiquement. Mais si les conventions ne sont pas respectées, vous avez toujours la possibilité de configurer vos modèles vous-même!

Prenons le schéma suivant :



Il ne respecte aucune des conventions d'ActiveRecord. Prenons la table 'my_users'. Son nom devrait être 'users' et sa clé primaire 'id'. Ici son nom est 'my_users' et sa clé primaire est 'my_pk'.

Je travaille avec une base Oracle, les champs auto-incrémentés comme en MySQL n'existent pas. Une séquence doit être utilisée à la place. Séquence que j'ai appelée 'my_users_autoi'.

Voici à quoi ressemble ma classe User:


class User < ActiveRecord::Base

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

end


Comme vous pouvez le voir, ce n'est pas sorcier. Vous pouvez maintenant manipuler votre modèle, toutes les opérations CRUD sont à votre disposition. Et lorsque vous insérez un nouvel utilisateur, vous pouvez constater que votre séquence est utilisée pour lui assigner sa clé primaire.

Un utilisateur peut écrire des articles. Il y a donc une relation de un à plusieurs entre ces deux entités. La classe article est assez classique, son nom est standard et elle possède un champs ID.
Le nom de la clé étrangère n'est cependant pas correct. Les conventions d'ActiveRecord demandent une clé étrangère nommée user_id.
Il faut donc la configurer dans notre modèle et également ajouter la relation dans la classe User:


class Article < ActiveRecord::Base

belongs_to :user, :foreign_key => 'by_user'

end

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



Vous pouvez alors commencer à minipuler vos données :

((
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'
))

Voilà déjà une bonne chose de faite. La table Ranking est cependant plus ennuyeuse.

Les utilisateurs peuvent voter pour des articles en attribuant un côte de 1 à 5.

La clé primaire de la table Ranking est composite : elle est basée sur BY_USER et FOR_ARTICLE.
Le problème est qu'ActiveRecord ne gère pas les clés primaires composites. Heureusement, il existe une librairie
permettant de combler ce manque
. Installez-la en suivant la démarche énoncée sur le site de l'auteur.

Une fois la manipulation effectuée, créez votre classe Ranking et modifiez vos précédentes classes pour refléter cette nouvelle 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


Vous pouvez maintenant permettre aux utilisateurs d'attribuer une note à un article :


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


Remarquez que vous devez spécifier explicitement la clé primaire (usr.my_pk) plutôt que de passer directement le modèle (usr).

Et bien voilà, je pense que vous pouvez maintenant affirmer que développer une application Rails basée sur un schéma existant est tout à fait réalisable. Et comme toujours, cela reste très simple!
Bookmark and Share

Ajouter un commentaire



2 commentaires pour cet article



This post rocks ! Thank you !


Ecrit par Ahava le 17 juin 2009 10:01

What about primary keys that are strings?


Ecrit par gerold le 24 septembre 2009 11:58