RJS introduction

Publié par Nico Mar 24 juil 2007 12:05:00 GMT

RJS is a powerful type of template used in Rails to generate Javascript code from the server-side. This code will be sent to and executed by the browser.

This generated Javascript code is written in Ruby and allows you to update multiple elements in the page very easily without reloading it.

In this article I’m going to show you how RJS works using a concrete example.

Real-world application

Let’s say that you have a TODO-list with a form that can be used to add a new task. When you add a new task you want to append this task to your existing list, use a visual effect to show that a task has been added and reset the form.

RJS is perfect for this kind of task, you just have to create a file named after your action name that is adding your task to the database. For example, if my action is add_task, I’m going to create a file named add_task.rjs.

My add_task action is creating an instance variable @task, so my RJS file should be something like :

page.insert_html :bottom, 'tasks_div', :partial => 'task'
page.visual_effect :highlight, 'tasks_div'
page.form.reset 'add_task_form'

The page object is actually generated by Rails and is an instance of the Rails JavaScriptGenerator. This page object translates your Ruby code to Javascript.

First, we ask Rails to insert the resulting content into the bottom of the tasks_div <div>. So the first parameter is the position where the new content will be inserted.

The second parameter is the id of the element that will be modified.

The third parameter can either be a string literal or hash that corresponds to the options you can pass to render method. In this exemple we’re asking Rails to render the partial _task.rhtml.

After that we are applying a visual effect to the <div> that has been modified. To do this, we’re using visual_effect. The first parameter is the name of the effect to use, the second one is the id of the element on which we want to apply this effect.

The last line is used to reset the form with the id add_task_form so all the fields of this form are cleared.

Using these basics and reading the Rails API, you can start doing AJAX / RJS.

What can I do with RJS?

Anything! or almost anything you want to be dynamic

The Page object provides many methods to manipulate Javascript using simple and clear Ruby code.

These helpers are :
  • << : writes raw JavaScript to the page
  • alert : displays an alert dialog
  • assign : assigns a value to a JavaScript variable
  • call : calls a JavaScript function
  • delay : executes the content of the given block after a delay
  • draggable : creates a script.aculo.us draggable element
  • drop_receiving : creates a script.aculo.us drop receiving element
  • hide : hides the given DOM elements
  • insert_html : inserts HTML at the specified position for the given DOM element
  • redirect_to : redirects the browser to the given location
  • remove : removes the given DOM elements from the page
  • replace : replaces the outer HTML of the given DOM element
  • replace_html : replaces the inner HTML of the given DOM element
  • select : returns a collection reference by finding it through a CSS pattern in the DOM
  • show : shows the given DOM elements
  • sortable : creates a script.aculo.us sortable element
  • toggle : toggles the visibility of the given DOM elements
  • visual_effect : starts a script.aculo.us visual effect
  • [] : returns an element reference by finding it through id in the DOM

Debugging RJS

When you’ll come to using RJS (and Javascript) a lot, you’ll definitely have to debug it. There are some powerful tools that can help you out and save you a lot of time (and headaches).

First of all, Rails provides a few built in tools to get your bugs resolved quickly. In development mode you have access to a lot of information in the log file.

If an unhandled exception is raised, you’ll get an error page rather than the expected one. This error page gives you information about the file that has raised the exception, on which line, etc.

Alert boxes will popup too.The first one tells you what is the exception and the second one shows you the generated javascript code that raised the exception.

The last tool to debug your RJS / Javascript code is Firebug. Firebug is a plugin for firefox which include a DOM inspector, a Javascript console, an XMLHttpRequest logger and a command-line javascript interpreter.

Conclusion

As you can see it’s very easy to implement Ajax features with Rails and RJS templates. You can really do a lot of things using RJS, this article only scratch the surface of RJS capabilities. Be sure that if you try it, you’ll implement some AJAX functionnalities in all your future projects.

Have fun!

Publié sous  | Mots clés ,  | aucun commentaires

Comprendre l'objet "self"

Publié par Nico Jeu 12 avr 2007 12:58:00 GMT

En Ruby, self représente l’objet courant. L’objet self va donc varier en fonction du contexte dans lequel vous vous trouvez. Il est initialisé et géré automatiquement par l’interpréteur.

La théorie

self peut se trouver dans les contextes suivant :
  • le contexte global (tout endroit qui ne correspond pas aux contextes suivants)
  • la définition d’une classe
  • la définition d’un module
  • la définition d’une méthode

Il y a quelques exceptions mais dans la majorité des cas, vous vous retrouverez dans le contextes précédemment cités.

Voici un tableau récapitulatif pour mieux vous y retrouver :
Contexte Exemple Que représente self ?
global Partout en dehors des blocs main (objet par défaut)
Classe class Test L’objet class Test
Module module M L’objet module M
Méthode Global main
Méthode d’instance L’instance de la classe
Méthode d’instance d’un module L’objet étendu par le module ou l’instance qui mixe le module
Méthode singleton L’objet étendu par le singleton

La pratique

Voyons maintenant une session IRB pour découvrir par l’exemple :
puts self
# => main
class C
  puts self # => C

  module M
    puts self # => C::M
  end

  def C.x
    puts self # => C
  end

  def x
    puts self # => Une instance de C
  end
end

Quelques explications

On dans l’exemple précédent que self se comporte de façon tout à fait logique en devenant l’objet par défaut qui paraît le plus évident.

  • en dehors de tout contexte, il représente l’objet main
  • on entre ensuite dans la définition de notre classe C est représente donc cet objet.
  • nous ajoutons un module à notre classe, self réprésente donc maintenant notre objet module C::M (puisque déclaré dans la classe C)
  • nous sortons du module et déclarons une méthode de classe, self va donc réprésenter notre classe C
  • finalement nous définissons une méthode d’instance et self réprésentera donc une instance de notre classe C

Conclusion

Comprendre ce que représente self à chaque instant et savoir le manipuler représente un aspect crucial dans la maîtrise de Ruby. Manipuler correctement self vous permettra d’aller beaucoup plus loin et plus vite lors de vos développement.

Publié sous  | Mots clés ,  | aucun commentaires

Intégrer Comparable à vos classes

Publié par Nico Jeu 12 avr 2007 09:14:00 GMT

Dans le dernier billet nous avons vu comment intégrer le module Enumerable à vos classes Ruby. Aujourd’hui nous verrons comment faire de même avec le module Comparable.

Comparable permet d’ajouter des méthodes de tri et de comparaison à vos classes telles que <, between?, sort.

Encore une fois il suffit d’écrire une méthode qui donnera les bases au module Comparable.

La théorie

Toute classe voulant utiliser les capactités du module Comparable doit implémenter une méthode <=>. Cette méthode doit pouvoir comparer deux objets sur un critère dont vous êtes le seul juge et renvoyer une valeur (-1, 0 ou 1) qui indique quel est le plus grand élément ou s’ils sont égaux.

On a par exemple :
1 <=> 2
# => -1
2 <=> 1
# => 1
2 <=> 2
# => 0

Définir <=> et inclure le module Comparable dans votre classe, c’est ajouter le possibilité à votre classe de trier des collections et d’effectuer des comparaisons entre deux objets.

Voyons maintenant comment mettre cela en place.

La pratique

Prenons un exemple simpliste mais qui résume bien la façon de mettre en place les fonctionnalités de Comparable dans vos propres classes. Nous allons écrire une classe qui pour ses comparaisons se basera sur la taille des chaînes qui lui sont passées.

 class Taille
   include Comparable
   attr :str

   def <=>(autre)
     str.size <=> autre.str.size
   end

   def initialize(str)
     @str = str
   end

   def inspect
     @str
   end
end

# Utilisation de la classe

s1 = Taille.new("Z")
s2 = Taille.new("YY")
s3 = Taille.new("XXX")
s4 = Taille.new("WWWW")
s5 = Taille.new("VVVVV")

s1 < s2
# => true
s4.between?(s1, s3)
# => false
s4.between?(s3, s5)
# => true
[ s3, s2, s5, s4, s1 ].sort
# => [Z, YY, XXX, WWWW, VVVVV]

En incluant le module Comparable ainsi qu’en définissant la méthode de comparaisons (<=>), on donc accès à toutes les méthodes de comparaison et de tri pour notre classe.

Quelques explications

Nous incluons tout d’abord le module Comparable pour préciser que l’on souhaite faire usage de ses possibilités.

Il ne nous reste plus qu’a écrire la méthode de comparaison (<=>) qui va se charger de comparer une spécificité de notre objet courant avec celle d’un autre objet passé en paramètre. Dans notre exemple, nous comparons la taille de la chaîne.

Voilà, nous avons maintenant à disposition dans notre classe tous les outils de comparaison dont nous avons besoin. Notre exemple le démontre en utilisant les méthodes <, between? et sort.

Conclusion

L’ajout de méthode de comparaison est donc chose aisée. Si votre classe a besoin de pouvoir comparer ses instances entre elles, pensez à inclure le module Comparable et à écrire une méthode <=>. Votre classe gagnera en quelques minutes la possibilité de comparer et trier ses instances.

Publié sous  | Mots clés ,  | aucun commentaires

Intégrer Enumerable à vos classes

Publié par Nico Jeu 12 avr 2007 08:22:00 GMT

Ruby étant un langage purement objet, il est fréquent de créer ses propres classes pour pouvoir accomplir une tâche donnée.

Dans bien des cas, le développeur veut pouvoir ajouter des fonctionnalités d’énumération à des objets d’une collection.

Pour arriver à cela, Ruby propose le module Enumerable que vous pouvez facilement intégrer à votre classe. Il suffit d’écrire votre classe en respectant quelques consignes et en indiquant à Ruby comment lister à l’intérieur de votre classe.

La théorie

Toute classe voulant utiliser les capactités du module Enumerable doit implémenter une méthode each. Le travaille de cette méthode sera d’envoyer les éléments de la collection un par un au bloc de code qui lui sera passé.

Si votre collection est contenu dans un tableau il vous faudra donc envoyer le premier élément du taleau, puis le second et ainsi de suite. Si votre collection est contenue dans un Hash, il vous faudra envoyer les éléments un par un sous forme de paires clef / valeur.

each peut être implémentée de nombreuses façon différentes selon les cas mais le principe reste toujours le même, envoyer des éléments significatifs un par un.

La majorité des méthodes implémentées par le module Enumerable se basent sur la méthode each pour faire leur travail. Une fois cette méthode définie dans votre classe vous aurez accès aux méthodes telles que find, reject, map, all? ...

La pratique

Voici un exemple qui vous permettra de voir comment intégrer Enumerable à votre classe. Nous allons travailler avec les couleurs de l’arc-en-ciel. Le travail de each sera donc de nous renvoyer les couleurs de l’arc-en-ciel, une par une :

class ArcEnCiel
  include Enumerable

  COULEURS = ["rouge", "orange", "jaune", "vert", "bleu", "indigo", "violet"]
  def each
    COULEURS.each { |c| yield c }
  end
end

a = ArcEnCiel.new
couleur = a.find { |c| c[0, 1] == "j" }
puts "La première couleur trouvée commençant par la lettre 'j' est le #{couleur}."

Vous noterez donc qu’on utilise la méthode find sans même l’avoir définie. Cette méthode fait partie du module Enumerable que nous avons inclus dans notre classe. Le module est en mesure de fonctionner grâce à notre méthode each.

Quelques explications

Nous incluons tout d’abord le module Enumerable pour préciser que l’on souhaite faire usage de ses possibilités.

Nous avons ensuite définie une constante de type tableau qui contient nos couleurs de l’arc-en-ciel. Nous pourrons donc parcourir ce tableau pour avoir accès aux différentes couleurs disponibles.

Nous définissons ensuite notre méthode each pour qu’elle renvoie (à l’aide de yield) nos couleurs une par une.

Le travail est fini, nous avons maintenant accès à toutes les méthodes du module Enumerable depuis notre classe comme le montre l’exemple d’utilisation de la méthode find.

Conclusion

Il est donc très facile d’ajouter à vos classes des capacités de listing et de traversée de collection. Si votre classe gère une collection d’objet, pensez à inclure le module Enumerable et à écrire une méthode each. Votre classe gagnera en puissance pour un surcoût de développement insignifiant.

Publié sous  | Mots clés ,  | aucun commentaires