27 mar
Publié par Cédric Bousmanne dans la catégorie Astuces
# app/controller/application.rb rescue_from ActionController::RoutingError, ActionController::UnknownAction, ActiveRecord::RecordNotFound do |exception| respond_to do |type| type.html { render :template => "shared/errors/404", :layout => 'application', :status => 404 } type.all { render :nothing => true, :status => 404 } end end
Si vous désirez pousser un peu plus loin cette méthode, vous pouvez bien sûr définir vos propres exceptions et en gérer les retours :
# lib/exceptions.rb module Exceptions class RestrictedToUsers < StandardError; end end # app/controllers/some_controller.rb def show raise Exceptions::RestrictedToUsers if !user # ... reste de votre code end # app/controllers/application.rb rescue_from Exceptions::RestrictedToUsers do |exception| respond_to do |type| type.html { render :template => "shared/errors/restricted_to_users", :layout => 'application' } end end
24 mar
Publié par Cédric Bousmanne dans la catégorie Astuces
Dans cet exemple, nous imaginons une application de type blog : nous disposons d’une liste d’articles à afficher sur une page d’index, et nous voudrions y insérer un système de pagination.
Commençons par créer le helper de pagination, RAILS_ROOT/app/helpers/pagination_helper.rb :
module PaginationHelper def paginate_for(max,limit=5) number_of_pages = (max%limit == 0) ? max/limit : (max/limit)+1 return if number_of_pages == 1 r = "<ul class='paginate'>" 1.upto(number_of_pages) do |i| if (params[:page].to_i == i) or (params[:page].nil? and i == 1) r += "<li><span class='current'>#{i}</span></li>" else r += "<li>#{link_to(i, :controller => params[:controller], :action => params[:action], :page => i)}</li>" end end r += "</ul>" (r) end end
Du côté du controlleur (RAILS_ROOT/app/controllers/blogs_controller.rb), nous avons besoin de deux données essentielles : le nombre d’articles à afficher (@blogs_size), et le nombre d’articles affichés par page (NUMBER_OF_BLOG_POST_PER_PAGE).
Nous calculons également l’offset en fonction de la page où nous nous situons.
class BlogsController < ApplicationController def index offset = (params[:page].nil?) ? 0 : (params[:page].to_i-1)*NUMBER_OF_BLOG_POST_PER_PAGE @blogs_size = Blog.count_by_sql("SELECT COUNT(*) FROM blogs") @blogs = Blog.find(:all, :order => "created_at DESC", :limit => NUMBER_OF_BLOG_POST_PER_PAGE, :offset => offset) respond_to do |format| format.html # index.html.erb end end end
Pour terminer, il ne reste qu’à faire appel a notre helper dans la vue RAILS_ROOT/app/views/blogs/index.html.erb, avant et/ou après la liste des articles :
<%= paginate_for(@blogs_size, NUMBER_OF_BLOG_POST_PER_PAGE) %>
Si mon objet foo a été créé le 3 février et que je souhaite afficher sa date de création, je vais faire ceci…
<%= foo.created_at.strftime('%d %B') %> # -> '03 February'
Pour éviter le 0 inutile devant le 3 et ainsi obtenir « 3 February », il convient d’ajouter le modificateur de préfixe ‘-1′ dans l’expression passée en argument.
<%= foo.created_at.strftime('%-1d %B') %> # -> '3 February'
(testé avec Rails 2.1.2)
03 fév
Publié par Vincenzo Ruggiero dans la catégorie Sécurité
En voilà un vrai problème de sécurité ! Lorsque vous demandez à vos visiteurs de spécifier un mot de passe (ou une confirmation de mot de passe) celui-ci est transmis à votre application sous forme de paramètre.
Le souci est que Rails ajoute tous les paramètres reçus/envoyés dans le fichier de log. Les mots de passes de vos utilisateurs se retrouvent donc en clair dans vos fichiers de logs.
Petit exemple, un formulaire d’identification:

Si j’envoie ce formulaire, voici ce qu’on retrouvera dans mon fichier de log:
Parameters: {"commit"=>"M'identifier", "password"=>"azerty12", "email"=>"vinc@pepperkoffee.com", "authenticity_token"=>"b9f0915b77ae33e6ca39cca16a1ecd65857b6e20", "action"=>"create", "controller"=>"sessions"}
On retrouve en clair mon mot de passe « azerty12« .
Pour éviter cela, nous allons simplement ajouter cette ligne dans le fichier RAILS_ROOT/app/controllers/application.rb:
UPDATE: Cette ligne est présente mais commentée dans Rails 2.2, décommentez-la.
class ApplicationController < ActionController::Base ... filter_parameter_logging "password" ... end
Envoyons une nouvelle fois notre formulaire, voici ce que nous trouvons dans les logs:
Parameters: {"commit"=>"M'identifier","password"=>"[FILTERED]", "email"=>"vinc@pepperkoffee.com", "action"=>"create", "authenticity_token"=>"b9f0915b77ae33e6ca39cca16a1ecd65857b6e20", "controller"=>"sessions"}
Notre mot de passe a été remplacé par « [FILTERED]« .
Sachez que filter_parameter_logging reçoit, notamment, son argument comme une expression régulière. Ce qui signifie que si un champ de votre formulaire s’appelle « password_confirmation », il sera aussi caché dans vos logs.
Pour plus d’informations sur filter_parameter_logging, consulter la documentation.
02 fév
Publié par Vincenzo Ruggiero dans la catégorie API, Identification, Sécurité
Vous avez certainement entendu parlé de Facebook ? Ce célèbre réseau social où tout le monde est inscrit …
Il faut savoir que Facebook propose depuis peu une API de connexion du nom de Facebook Connect.
On peut comparer Facebook Connect à OpenID. Les deux reposent sur l’idée d’une identification/inscription unique. Vous vous inscrivez sur Facebook et vos identifiants et mots de passe peuvent ensuite être utilisés pour vous connecter à d’autres sites.
L’avantage de Facebook Connect réside dans le fait que beaucoup de gens sont déjà inscrits sur le site, évidemment …
Je vais donc vous proposer un tutoriel complet permettant de mettre en place une identification via Facebook Connect sur votre site.
Lire la suite »
01 fév
Publié par Cédric Bousmanne dans la catégorie Astuces
Dans certaines situations, il peut être intéressant de pouvoir distinguer les utilisateurs humains des robots d’indexations des moteurs de recherche. Dans cet article, nous allons voir comment effectuer cette distinction en quelques lignes seulement.
Ajoutez la méthode suivante dans votre contrôleur d’application (RAILS_ROOT/app/controllers/application.rb) :
# Return true if the user agent is a bot. def robot? bot = /(Baidu|bot|Google|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg|ia_archiver|MJ12)/i request.user_agent =~ bot end
Désormais, il vous sera possible d’utiliser cette méthode dans n’importe quel contrôleur. Par exemple :
def show render :update do |page| if robot? page.alert("je suis un robot") else page.alert("je ne suis pas un robot") end end end
La liste des robots définie dans la variable bot est bien entendu non-exhaustive, libre à vous de la compléter selon vos propres besoins.
Le lien standard de Ruby on Rails se compose sous cette forme:
http://domain.com/:controller/:action/:id
Imaginons une table « films » avec son controller « films » ainsi que son model « film« . Un film est identifié par les colonnes « ID » et « TITLE« .
L’URL permettant de visualiser le film « Le parrain » dont l’ID est 14 serait:
http://domain.com/films/show/14
Il serait intéressant d’ajouter le titre du film à cette URL, comme ceci:
http://domain.com/films/show/14-le-parrain
Pour se faire, rien de plus simple, dans le model « film« , ajoutez ceci:
class Film < ActiveRecord::Base ... def to_param "#{id}-#{title.gsub(/[^a-z1-9]+/i, '-')}" end ... end
Modifiez ensuite l’argument :id du link_to:
# Avant link_to 'Le parrain', :controller => :films, :action => :show, :id => @film.id # Après link_to 'Le parrain', :controller => :films, :action => :show, :id => @film
En spécifiant l’objet à l’argument :id vous obtiendrai le lien contenant le titre du film.
30 jan
Publié par Michael Hulet dans la catégorie Javascript
Lightview est un script JavaScript permettant d’afficher une pop-up dynamique par-dessus une page web. Nous nous en servons beaucoup sur l’un des projets en cours.
Dans l’une des « lightviews » dont le contenu est chargé en AJAX, nous affichons une liste d’objets paginée à l’aide du gem/plugin will_paginate.
Nous voulons que les liens internes de la lightview chargent eux aussi du contenu en AJAX, dans la même lightview. C’est tout à fait possible, la documentation de Lightview vous expliquera comment faire.
Cependant, le plugin will_paginate ne permet pas directement de spécifier les attributs ‘class’, ‘rel’ et ‘title’ des liens de paginations générés. Ce doit être possible en modifiant le LinkRenderer du plugin, mais il y a plus simple.
Pour que les liens générés par will_paginate agissent eux-mêmes en AJAX dans la lightview, voici comment faire. Insérez le code ci-dessous au bas de votre vue.
<div id="pagination-wrapper">
<%= will_paginate @posts %>
</div>
<script type="text/javascript">
//<![CDATA[
pagination_links = $('pagination-wrapper').getElementsByTagName('a');
for (i = 0; i < pagination_links.length; i++) {
pagination_links[i].setAttribute('class', 'lightview');
pagination_links[i].setAttribute('rel', 'ajax');
pagination_links[i].setAttribute('title', 'Mon super blog :: :: autosize: true, ajax: { evalScripts: true, method: \'get\' }');
}
Lightview.updateViews();
//]]>
</script>30 jan
Publié par Vincenzo Ruggiero dans la catégorie Déploiement, Plugins
Un plugin plus que pratique, indispensable. exception_notification vous enverra un eMail à chaque erreur qui se produit dans votre application.
Pour l’installer :
script/plugin install git://github.com/rails/exception_notification.git
Ensuite, ajoutez cette ligne dans le fichier RAILS_ROOT/app/controllers/application.rb:
class ApplicationController < ActionController::Base include ExceptionNotifiable ... end
Enfin, dans votre fichier d’environement (RAILS_ROOT/config/environment.rb):
ExceptionNotifier.exception_recipients = %w(email@domaine.com autre_email@domaine.be)
Vous spécifiez donc autant d’adresses eMail que vous le souhaitez, dès qu’une exception se produit dans votre application, vous recevrez un email détaillé.
29 jan
Publié par Michael Hulet dans la catégorie Déploiement, Serveurs
On dit beaucoup de bien de Phusion Passenger couplé à Ruby Enterprise Edition. Si vous voulez vous lancer dans l’aventure, voici les commandes de base à exécuter (sous Debian).
sudo apt-get install ruby rdoc irb ruby1.8-dev sudo gem install passenger sudo passenger-install-apache2-module cd /home/michael/sources wget { dernière version de ruby enterprise } tar xvzf { fichier que vous venez de télécharger } sudo ./ruby-enterprise-X.X.X/installer sudo /opt/ruby-enterprise-X.X.X-YYYYMMDD/bin/passenger-install-apache2-module
L’installer est très bien fait et vous donnera les noms exacts des éventuels paquets manquants.
Après, il ne reste plus qu’à lire la doc: Phusion Passenger et Ruby Enterprise Edition. Chance pour nous, elle est plutôt bien faite.