Tutorial : créer sa première application Ruby on Rails - Part3
Par jblanche le mardi 28 août 2007, 22:08 - geeks - Lien permanent
Après une trêve due à de trop courtes mais bien agréable vacances, voici la suite de la création de notre application.
Dans ce tutorial, nous apprendrons à rajouter des tags à notre application.
Pour ce faire, je me suis largement inspiré d'un autre tutorial sur stoneageblog.com.
Comme souvent, avec Rails inutile de ré-inventer la roue, et quand ce n'est pas le framework qui vous simplifie la vie, c'est la communauté qui vient à votre secours.
J'ai donc utilisé pour ce tutorial le plugin acts_as_taggable_on_steroids, un plugin servant à créer facilement un système de tags dans votre application.
Pour ce faire, il est nécessaire d'exécuter dans une console à la racine de notre application le script suivant :
script/plugin install http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids/
Une fois le plugin installé, il est nécessaire d'ajouter une migration afin de créer les tables nécessaires à l'introduction des Tags.
script/generate migration add_tags
Remplissez le fichier précédemment crée comme ceci :
class AddTags < ActiveRecord::Migration
def self.up
create_table :tags, :force => true do |t|
t.column :name, :string
end
create_table :taggings, :force => true do |t|
t.column :tag_id, :integer
t.column :taggable_id, :integer
t.column :taggable_type, :string
t.column :created_at, :datetime
end
end
def self.down
drop_table :tags
drop_table :taggings
end
end
Nous créons donc deux tables, la première contiendra les noms des différents tags, la seconde les associe à un objet de type taggable_type qui pour nous sera un Snippet et au taggable_id de l'objet en question.
Cette méthode appelée Polymorphisme permettrait d'appliquer les tags à d'autres modèles (Catégories...) par la suite.
Pour exécuter cette migration, c'est vous commencez à en avoir l'habitude en console que ça se passe.
rake db:migrate
Pour parachever la partie base de données, indiquons à notre modèle Snippet qu'il est taggable (ou susceptible d'être taggé). Pour cela, il suffit d'ajouter la ligne acts_as_taggable dans notre modèle afin d'obtenir quelquechose comme ceci.
class Snippet < ActiveRecord::Base
acts_as_taggable
...
end
Notre base de données est désormais prête à accueillir nos tags, nous allons donc les ajouter au formulaire d'ajout de nos Snippets dans le controller Admin.
Dans la vue new.rhtml, je rajoute le code suivant :
<%= content_tag :label , "Tags (separated by a comma)", {:for=>"cd_tag_list"} %>
<%= f.text_field :tag_list %>
Et voilà, rien de plus ne sera nécessaire, l'ajout des tags à notre application est déjà effectif et une multitude de méthodes sont à notre disposition pour les utiliser. Pour les afficher, je peut par exemple désormais faire :
<%= content_tag :p, @snippet.tag_list, :class => "tag_list"%>
Nos Snippets sont désormais taggués mais il manque un petit nuage de tags afin de rendre cette application vraiment Web2.0 :-D.
Pour ce faire, nous allons créer une méthode tag_cloud dans le helper de notre controller snippets(on pourrait tout aussi bien le mettre dans appliucation_helper si l'on souhaite l'afficher dans l'admin.)
Cette méthode, la voiçie (encore merci à l'article de stoneageblog)
def tag_cloud(tags, classes)
max, min = 0, 0
tags.each { |t|
max = t.count.to_i if t.count.to_i > max
min = t.count.to_i if t.count.to_i < min
}
divisor = ((max - min) / classes.size) + 1
tags.each { |t|
yield t.name, classes[(t.count.to_i - min) / divisor]
}
end
Dans un premier temps, la méthode cherche la fréquence des tags les plus et les moins utilisés.
Dans un deuxième temps, elle affecte à chaque tags une classe CSS en fonction de sa propre fréquence.
Pour ce faire, vous devrez donc définir plusieurs styles dans vos CSS.
/* Nuage de Tag*/
.nube1 {font-size: 1.0em;}
.nube2 {font-size: 1.2em;}
.nube3 {font-size: 1.4em;}
.nube4 {font-size: 1.6em;}
.nube5 {font-size: 1.8em;}
.nube6 {font-size: 2.0em;}
Comme je souhaite afficher ce nuage de tags pour toutes les méthodes du controller Snippets (dans la sidebar), j'ai choisi d'ajouter ma propre méthode au controller et de l'appeler pour chaque action.
J'ajoute donc une méthode private (pas accessible directement depuis le web)
private
def tag_cloud
@tags = Snippet.tag_counts(:order=>'tags.name asc')
end
Puis j'indique au controller d'éxécuter cette méthode avant chaque appel aux autres actions en ajoutant un before_filter à notre controller.
class SnippetsController < ApplicationController
before_filter :tag_cloud
...
end
Reste à afficher ce nuage de tag dans nos vues.
Celui ci étant toujours afficher, je l'ai placé directement dans le layout de notre controller (app/views/layouts/snippets.rhtml)
<% tag_cloud @tags, %w(nube1 nube2 nube3 nube4 nube5) do |name, css_class| %>
<%= link_to name,{:controller=>"snippets", :action=>"tagged", :tag=>name} ,:class => css_class %>
<% end %>
Comme toujours, c'est quand on croit en avoir fini que l'on découvre nos oublis. Avoir un nuage de tags, c'est bien joli, mais pouvoir associé à chaque tag une page ou l'on affichera les snippets taggués par celui ci, ça serait quand même plus sympa.
Je vous je propose donc, comme on peut le voir dans le link_to du code précédent, de lier chaque tag vers une page /snippets/tagged?tag=montag.
La méthode tagged n'étant bien sûre pas une méthode de l'architecture REST, il va falloir indiquer à rails que celle ci existe en ajoutant une ligne dans notre fichier routes.rb :
map.resources :snippets, :collection => { :tagged => :get }
Cette ligne indique à rails que le controller snippets bénéficie d'une méthode "tagged" qui retourne une collection (une liste) de snippets et qui sera appelée en utilisant la méthode GET.
Je peut donc écrire dans mon controller la méthode tagged comme ceci :
def tagged
@snippets = Snippet.find_tagged_with(params[:tag])
render :action => :index
end
La encore, la méthode find_tagged_with nous est fournie par le plugin acts_as_taggable_on_steroids, ce qui nous simplifie bien la vie
Voilà je crois que c'est tout pour les tags.
L'application à également bénéficié d'un relooking grâce au plugin Skinnable sur lequel je ne reviendrais pas tellement il est facile à mettre en place.
L'application en ligne est plus avancée que dans nos tutos puisque qu'elle bénéficie déjà d'un système de commentaires, de la coloration syntaxique des blocs de code, ainsi que de l'autocomplétion sur les tags qui feront l'objet des prochains tutos.
Le résultat est visible dans mon dépôt de snippets de test
Vous pouvez comme toujours, télécharger le code de l'application.
A bientôt pour la suite
Commentaires
Si j'étais dev (et il parait que je ne le suis pas) je serais content. Alors je suis quand même content, mais je comprends pas trop pourquoi. En tout cas, belles colorisations syntaxique :D
Fil des commentaires de ce billet