vendredi, juin 23, 2006

Comment faire de la documentation en ruby avec RDoc et Rake

C'est très simple, il suffit de créer un fichier Rakefile et de mettre:

# Generate the RDoc --------------------------------
Rake::RDocTask.new { |rdoc|
  rdoc.rdoc_dir = 'doc'
  rdoc.title    = project_title
  rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
  rdoc.rdoc_files.include('README', 'CHANGELOG')
  rdoc.rdoc_files.include('lib/**/*.rb')
  rdoc.rdoc_files.include('examples/**/*.rb')
}
Les fichiers README et CHANGELOG sont importants mais simple à faire... (il suffit de suivre la syntaxe de RDoc).
Voilà 2 exemples de ce qu'on peut mettre dedans:
README
== Google Calendar
The Google Calendar project provides 
* Export features (text file, simple html page or excel files), 
* Ruby api's to connect to google calendars 
* A plugin for Ruby On Rails.

== License
GoogleCalendar for Ruby is released under the Apache license.

== Support
http://rubyforge.org/projects/googlecalendar/

== Author
Benjamin Francisoud  - http://rubyscube.blogspot.com
CHANGELOG
= Versions

=== 0.0.2 (June 16th, 2006)
* Refactor googlecalendar to a single rb file
* Add Rakefile
* Add Gem, Zip, Tar packaging
* Add RDoc

=== 0.0.1 (Mai 11th, 2006)
* Started project

= About Versioning
* Version number: major.minor.build
* Compatible release (increment the build number)
* Backward compatible, new feature release (increment minor number)
* Backward incompatible release (increment the major number)


Finallement, le plus important, il suffit de lancer la commande:
>rake rdoc et hop plein de jolies pages html de doc api référence ;)

Comment créer un gem ?

La manière simple: Créer un fichier googlecalendar.gemspec par exemple. Ajouter le code suivant (à modifier selon les besoins)

spec = Gem::Specification.new do |s|
  s.name = 'googlecalendar'
  s.version = '0.0.2'
  s.summary = "Google Calendar api for Ruby."
  s.description = %{The Google Calendar project provides: Export features (text file, simple html page or excel files), Ruby api's to connect to google calendars, A plugin for Ruby On Rails.}
  s.files = Dir['lib/**/*.rb'] + Dir['test/**/*.rb'] + Dir['plugins/googlecalendar/lib/**/*.rb']
  s.require_path = 'lib'
  s.autorequire = 'googlecalendar'
  s.has_rdoc = true
  s.extra_rdoc_files = Dir['[A-Z]*']
  s.rdoc_options << '--title' <<  'googlecalendar -- Google Calendar api for Ruby.'
  s.author = "Benjamin Francisoud"
  s.email = "cogito@rubyforge.org"
  s.homepage = "http://benjamin.francisoud.googlepages.com/googlecalendar"
end
Exécuter la ligne de commande:
gem build googlecalendar.gemspec

Automatiser avec Rake: Tout est déjà fait dans Rake pour faire des gems facilement, il suffit de mettre pratiquement le même code que ci-dessus dans un fichier Rakefile:

project_name = 'googlecalendar'
# Create compressed packages
spec = Gem::Specification.new do |s|
  s.name = project_name
  s.version = current_version
  s.summary = project_title
  s.description = %{The Google Calendar project provides: Export features (text file, simple html page or excel files), Ruby api's to connect to google calendars, A plugin for Ruby On Rails.}
  s.files = ["README", "CHANGELOG"] + Dir['lib/**/*.rb']
  s.require_path = 'lib'
  s.autorequire = project_name
  s.has_rdoc = true
  s.rubyforge_project = project_name
  s.author = "Benjamin Francisoud"
  s.email = "cogito@rubyforge.org"
  s.homepage = "http://benjamin.francisoud.googlepages.com/googlecalendar"
end
  
Rake::GemPackageTask.new(spec) do |p|
  p.gem_spec = spec
  puts "----------------------------------------------------------------------------"
  puts "WARNING: You need to install cygwin (Archive package) for this task to work!"
  puts "----------------------------------------------------------------------------"
  p.need_tar = true
  p.need_zip = true
end
Si on veut faire des zip et des tar en plus du gem, il faut pouvoir faire en ligne de commande sous windows >zip ...et >tar... donc installer cygwin est surement la meilleure solution ;)

Publier un gem: Il y a plein de manières différentes (voir la documentation de gem)...
Mais la plus simple reste de faire un projet sous rubyforge pour stocker son projet.
Après avoir créé son gem+zip+tar avec le Rakefile, il suffit dans rubyforge de publier des fichiers pour une certaine release et de spécifier que le .gem qu'on a uploadé est un gem (via une select box)
Automatiquement rubyforge va s'occuper de le publier sur le server de gem principale et le gem sera disponible peu de temps après en faisant:
gem list --remote --details googlecalendar

jeudi, juin 22, 2006

[Rails] Table de correspondance type Ruby et type MySQL

Table de correspondance type Ruby et type MySQL:
Type SQLClasse Ruby
int, integerFixnum
decimal, numericFloat
interval, dateDate
clob,blob,textString
float, doubleFloat
char, varchar, stringString
datetime, timeTime
booleancompliqué...

Cas particulier du Boolean: le problème c'est que pour Ruby tout ce qui n'est pas nil ou la constante false est interprété comme true. Donc si la colonne contient 0 pour dire false, ruby va croire que c'est vrai...
Pour interpréter 0 comme false, il faut ajouter ? à l'attribut, exemple: user.admin? avec admin un colonne type TINYINT.

[Rails] La couleur 1 ligne sur 2

Dans Rails pour avoir la couleur, une ligne sur deux, il faut faire dans la vue:
<table%>
<% odd_or_even = 0  
5.times do  
odd_or_even = 1 - odd_or_even %>
<tr class="Ligne<%=odd_or_even%>"%><td%>XXX</td%></tr%>
<%end%%>
</table%>
Avec dans la css:
.Ligne0 {background-color:gray;}
.Ligne1 {background-color:white;}
Mais je trouve que c'est mieux fait dans JSF... Rem: odd_or_even est possible grâce à l'ajout des méthodes even? et odd? à Fixnum.

[Rails] Les liens

Pour faire un lien avec Rails il suffit d'utiliser "link_to", exemple:
<%= link_to 'Identification', :action => 'login'%>
Et d'avoir la méthode login dans le controleur correspondant...

[Rails] Le controleur

l'URL: http://localhost:3000/user/login Correspond au controleur: app/controlers/user_controller.rb
  • user = UserController
  • login = la méthode login dans UserController

Simple n'est ce pas?

[Rails] Sessions

Les sessions fonctionnent comme en Java - J2EE (pour ceux qui connaissent). Depuis un controleur:

session[:user] = User.new # pour creer l objet
session[:user] #pour l'utiliser

On peut utiliser la ligne suivante pour récupérer l'objet et le créer s'il n'existe pas:

session[:user] ||= User.new

Attention, comme dans une appli J2EE, il vaut mieux ne pas trop mettre d'objet en session...

switch , case, when

Ca! C'est quelque chose que je ne trouve pas cool du tout en ruby! Dans tous les languages que je connais (java, javascript, C++...) on utilise switch/case:

public class Test {

 public void test(int key) {
  switch (key) {
  case 1:
   System.out.println("1");
   break;
  default:
   System.out.println("default");
   break;
  }
 }
}

Et en Ruby c'est case/when:
def switch_test(count)
  case(count)
    when 0: puts "zero"
    when 1: puts "un"
    else puts "else"
  end
end

switch_test(1)
switch_test(0)
switch_test(4)

Résultat:
un
zero
else

Je ne trouve pas ça plus clair et surtout je vais me mélanger avec les autres languages à tous les coups!

Itération dans une table de Hashage

def print_hash
  personnes = {{1, "maurice"}, {2, "marcel"}}
  
  personnes.each do |num, prenom| 
    puts num
    puts prenom
  end
end

print_hash

[Rails] Validation

Dans la rails la validation est très simple, il suffit d'aller dans son objet métier, par exemple dans : app/models/livre.rb:

class Product < ActiveRecord::Base
  validates_presence_of :isbn
  validates_length_of :isbn, :maximum => 10, :message => 'max 10 char'
  validates_numericality_of :prix
  validates_uniqueness_of :titre
  validates_format_of :image_url, :with => %r{^http:.+\.(gif|jpg|png)$}i, message => 'doit être un URL ou une image GIF, JPG ou PNG'

protected
def validate
  errors.add(:prix, 'doit être positif') unless prix.nil? || prix > 0.0
end

Pour plus d'informations: HowtoValidate
Ou alors: la liste des validateurs.
Et si ça suffit pas, on peut créer nos propres règles (voir la fonction validate).

YAML Ain't Markup Language

YAML est utilisé dans Rail pour la configuration des bases de données.
  • avantages: plus clair que xml et moins limité que les .properties
  • inconvénient: il y a moins de librairies/outils pour parser ce genre de documents que XML - mais une seule bonne librairie ruby suffit ;)

[Rails] Les conventions de nommage - la suite

Par convention dans les applications Rails:

Type de colonne dans la BDDModel de champsExemple
datetimexxx_atlast_edited_at
datexxx_onsend_on

Conséquence: si on crée une colonne "created_at" dans une table, elle est automatiquement remplie!

La différence entre simple quote et double quote

Le texte entre double quote est interprété. Les \n sont transformés en retour chariot etc...
Le texte entre simple quote est utilisé tel quel.

Définir un tableau de constantes

[tableau].freeze

[Rails] Trouver une ligne unique dans la base de données

Dans le controleur:
def login(name, password)
 find(:first, :conditions => ["name = ? and password = ?", name, password])
end

Installer un environnement Ruby / Rails / Eclipse sous windows

Comme je suis feigant et que d'autres l'on déjà expliqué, il suffit de suivre le lien (et de comprendre l'anglais):

[Rails] Liste de sélection

Dans la vue:
<% 
options = Order::PAYMENT_TYPES
select('order', 'pay_type', options)
%>
  • order = objet / table
  • pay_type = attribut / colonne
Dans app/models/Order.rb:
PAYMENT_TYPES = [['check', 'check'], ['Credit card', 'cc'], ['Master Card', 'mc']].freeze

[Rails] Gérer les utilisateurs et l'identification / login

Dans pratiquement toutes les applications sur lesquels j'ai travaillé il y avait un système d'identification/login.

Plutôt que de réinventer la roue, Rails propose des générateurs à télécharger pour générer ce genre de code avec tous les aspects sécurités déjà géré: encoding des mots de passes.... Cool!

Vous pouvez trouver pleins d'autres liens plus à jour sur mon del.icio.us

[Rails] Updater Rails

Pour updater Rails c'est à la fois simple et compliqué :( Pour updater Rails en lui-même c'est simple, il suffit de lancer la commande:

gem update rails
gem propose d'updater les dépendances, il suffit de dire [Y].

Par contre l'application rails généré avec Rails 0.9, devrait continuer à fonctionner.
Mais si on génère une nouvelle application de zéro avec Rails 0.14 et qu'on fait un diff entre l'appli généré de zéro en 0.9, on va voir qu'il y a beaucoup de changements!!!

Donc en ce qui concerne la mise à jour de l'appli généré, il suffit de chercher parmis les taches rake pour trouver des taches qui simplifie la migration des versions de rails

Mais il faudra aussi penser à enlever les méthodes deprecated qui ont été généré avant l'update... pour plus de propreté ;)
Exemple:

render_partial 'form'
est deprecated et est remplacé par
render(:partial => ...)
Par exemple si le generateur de code n'est pas encore à jour et génère toujours du code deprecated...

[Rails] Les helpers

Les méthodes ajoutées dans app/helpers/utilisateur_helper.rb sont disponibles dans les vues du controleur: utilisateur_controller.rb. C'est à dire app/views/utilisateur/*.rhtml

Si on place une méthode dans application_helper.rb, cette méthode est disponible pour toutes les vues (exemple: un formateur de numéro de téléphone français...).

Les méthodes qui finissent en ! ou ?

En Ruby, par convention, les méthodes qui finissent en ! ou ? veulent dire quelque chose de particulier:

  • ? = la méthode renvoie un boolean
  • ! = la méthode fait quelque chose de destructif (vider une liste, renplacer une partie de la valeur passée en paramètre...)

[Rails] Gestion des erreurs

Comment afficher des messages d'erreur? Dans le controleur:

def mon_action
 flash[:notice] = 'Invalid product'
end

Dans la vue:

<%=@flash[:notice]%>

[Rails] Objets en session

Dans Rails si on met un objet en session, il faut bien penser à le déclarer dans app/controllers/application.rb, exemple:

class AdminController < ApplicationController
 model :cart
 model :line_item
end

[Rails] Les paramètres de requètes

On a souvent besoin d'utiliser des paramètres entre les pages et le controller, comment faire en Rails ?
Dans la vue:

<%=link_to 'Ajouter un utilisateur', {:action => 'add_user', :id => user}, class => 'mon_style'%>


Dans le controller:

def add_user
 user_id = params[:id]
end

[Rails] Afficher 1 liste de ligne de la base de données

Dans app/models/Utilisateur.rb
class Utilisateur < ActiveRecord::Base
 def self.utilisateurs_actifs
  find(:all, :condition => "actif == 1", :order => "date_creation desc")
 end
end

Utilisation:
Dans le app/controllers/utilisateur_controller.rb
def mon_action
 @utilisateurs = Utilisateur.utilisateur_actifs
end

Dans app/views/utilisateur/mon_action.rhtml
<ul>
 <% for utilisateur in @utilisateurs %>
 <li><%=utilisateur.nom%></li>
 <%end%>
</ul>

[Rails] Formater les chiffres décimaux

Dans la vue on peut utiliser:
<%=sprintf("%0.2f", prix);%>
Ou encore mieux utiliser un helper déjà contruit dans Rails, exemple:
<%=number_to_currency(prix, {:unit => "£", :separator => ",", :delim => "",:precision => 2})%>
Rem: Attention je n'ai pas testé toutes ces options.
Rem2: il est possible de voir tous les helpers disponibles dans le svn.

[Rails] Pourquoi je recopie le livre de Dave Thomas ?!

Parce qu'il est super bien fait! Le mieux c'est de l'acheter pour vous rendre compte par vous même ;) http://www.pragmaticprogrammer.com/titles/rails/index.html

vendredi, juin 16, 2006

Syntaxe RDoc

J'ai eu un peu de mal à la trouver alors je mets le lien ici vers la doc sur la syntaxe d'un fichier RDoc: http://www.ruby-doc.org/stdlib/libdoc/rdoc/rdoc/files/rdoc/markup/simple_markup_rb.html Les plus intéressants :
* this is a list with three paragraphs in the first item. This is the first paragraph.
*word* displays word in a bold font
_word_ displays word in an emphasized font  
+word+ displays word in a code font
Technorati tags: