Envoyer un email dans un model DataMapper

Avec Merb-mailer, merb fourni un système d'envoi d'email. Par contre merb étant un framework web se voulant ORM agnostique, merb-mailer est considéré comme un controller et non comme un model. De ce fait l'utilisation de la méthode send_mail n'est disponible que dans les controllers. Mais alors comment utiliser la méthode send_mail dans son model ? C'est très simple. Là encore merb utilise un système entièrement ruby ce qui facilite le méchanisme

Après une courte recherche dans le code de merb-mailer, j'ai pu constater que que la commande send_mail était dans un mixin. l'inclusion de ce mixin suffit donc à avoir la commande pour l'utiliser.

class Member
  include DataMapper::Resource
  include Merb::MailerMixin

  property :id, Serial
  property :name, String

  def register
    // some code
    send_mail (UserMailer, :register, {
        :from => "no-reply@example.com",
        :to => person.email,
        :subject => "Please activate your account" 
    }
  end

English translation

[...]
Published on Sam 20 déc 2008 20:19
0 commentaires

Supprimer tous les messages d'anonyme du forum redmine

Si comme moi vous avez ouvert le forum Redmine au anonyme pour éviter qu'un utilisateur ne soit obligé de s'inscrire pour poster sur le forum, vous êtes sujet au Spam, vu que Redmine n'a encore aucun système anti-spam. Vous pouvez ainsi vous retrouver dans cette position.

screenshot de mon forum redmine spammé

Une fois que vous avez bloqué l'ajout de message par les anonymes, il faut maintenant faire le ménage. Soit, vous prenez message par message et faite le bouton supprimer. Soit vous utilisez la console comme moi. Voici donc les commandes à réaliser pour supprimer tous les messages d'anonyme du forum. Bien-sûr, cela implique que si vous avez des utilisateurs qui ont posté en tant qu'anonyme, leur poste sera détruit.

rails@shinydedi /var/rails/redmine/current $ ./script/console production                                                                                                                          
Loading production environment (Rails 2.0.2)
>> User.anonymous
=> #<AnonymousUser id: 4, login: "", hashed_password: "", firstname: "", lastname: "Anonymous", mail: "", mail_notification: false, admin: false, status: 0, last_login_on: nil, language: "", auth_source_id: nil, created_on: "2008-01-26 16:39:30", updated_on: "2008-01-26 16:39:30", type: "AnonymousUser">
>> User.anonymous.id
=> 4
>> Message.find_all_by_author_id(User.anonymous.id).size
=> 1693
>> Message.find_all_by_author_id(User.anonymous.id).each { |me| me.destroy }
=> [.........]
>>

English translation

[...]
Published on Mar 04 nov 2008 07:19
0 commentaires

Afficher les Log SQL avec Merb et DataMapper

Depuis peu, je tente d'utiliser Merb et DataMapper. Une différence notable entre Merb et Rails est le système de log. Comme Merb est ORM Agnostique, il n'affiche pas de base les logs SQL. J'ai cherché plusieurs fois comment avoir mes logs SQL de DataMapper directement dans ma console. J'ai fini par la trouvé sur le wiki de DataMapper. Je vous livre donc l'astuce :

Merb::BootLoader.after_app_loads do
  DataObjects::SQlite3.logger = DataObjects::Logger.new(STDOUT, :debug) 
end

Vous pouvez bien-sûr modifier le SQlite3 par Postgres ou MySQL. Cette comment fait une sortie en mode debug sur STDOUT. On aurait aussi pu mettre un fichier ('log/dm.log').

Pour connaitre la liste des niveaux de logs, la voici :

  • fatal
  • error
  • warn
  • info
  • debug
[...]
Published on Ven 27 juin 2008 11:43
0 commentaires

Le piege des routes à éviter

Alors, que je testais Pictrails pour la release en version 0.3, j'ai par hasard créé une galerie s'appelant "new". Ayant implémenté un système de PrettyURL pour pictrails, j'ai changé les routes REST pour non pas afficher l'id de la galerie dans l'url mais son nom. Ainsi, comme ma galerie s'appele "new", je devais allez sur l'URL : /galleries/new.

Mais voilà comme galerie était une ressource REST, la route /galleries/new est déjà réservé et je me suis donc retrouvé sur l'url de création d'une Gallerie et non sur l'url de visualisation de la galerie new. C'est ainsi que je suis tombé dans le piège des routes à éviter.

Maintenant, que j'ai trouvé le bug il a fallu trouvé la solution et plus que de trouver la solution, il fallait trouver une solution propre. En effet, basiquement, on peux créer un validateur qui vérifie que le nom n'est pas "new", mais cette technique ne me semblait pas idéal surtout pour l'avenir et le maintient à terme de cette solution. J'ai donc commencé à en discuter avec les personnes présentent sur le chan #rubyonrails.fr. C'est ainsi que webs m'a proposé une solution tout à fait élégante en me donnant un code de sunny. La vérification directe de l'existence ou non de la route. Voici le bout de code qui permet cette vérification :

permalinks = ActionController::Routing::Routes.routes.collect {|r|
   r.generation_structure.match(/"\/galleries\/([\w]+)/)[1] rescue nil
}.uniq.compact

On récupère ainsi tous les mots utilisés dans nos routes et commençant par galleries. Sur Pictrails, nous obtenons ainsi "pages" et "new". Il suffit ensuite d'empêcher la création de galerie avec ces noms.

[...]
Published on Mar 17 juin 2008 10:29
4 commentaires

Où compiler ses fichiers C issue de RubyInline

RubyInline est un joli petit gem qui permet de générer du code C a partir de code Ruby. Ce code C est ensuite compilé et réutilisé durant les appels futurs de la méthode.

Par défaut, RubyInline compile tout dans votre dossier $HOME/.inline. Mais comment faire si l'utilisateur n'a pas de HOME par exemple, où tout simplement qu'il souhaite mettre la compilation dans le dossier $RAILS_ROOT/tmp/inline qui pourrait être une place tout à fait raisonnable.

N'ayant pas trouvé l'information dans la documentation de ce gem, j'ai donc chercher un peu dans le code. J'ai ainsi découvert que le dossier de compilation des fichiers C est géré par la variable d'environnement INLINEDIR. Il suffit donc de définir cette variable dans votre fichier d'environnement.rb pour choisir où sera compilé les fichiers générés par RubyInline.

[...]
Published on Ven 13 juin 2008 12:14
0 commentaires

quand la vue modifie son layout

Cas d'utilisation

Dans l'administration de Typo, en fonction du controller appelé, voir de l'action, il faut modifier la partie indiquant le sous-menu. On a donc 3 possibilités pour réaliser cette partie dynamique.

  1. Mettre la partie variable directement dans la vue et l'enlever du template.
  2. Mettre les informations directement dans le controller ou l'action et c'est cette information qui sera lu par le template
  3. Utiliser content_for directement dans la vue en utilisant le yield dans le template

Bien sûr la meilleur méthode est la troisième. Mais je vais expliquer pourquoi et comment on peux mettre en oeuvre.

Mettre la partie variable directement dans la vue et l'enlever du template

Cette méthode est de loin la plus simple qui soit. On sait que notre partie n'est pas toujours affiché pour le layout indiqué, donc on la met pas dans le template. Mais voilà, si on a du code entre notre partie dynamique et le vrai contenu de notre vue, on a pas le choix il faut dupliquer cette partie et ainsi on se retrouve à faire plein de copier coller et comme on sait le copier coller c'est pas DRY. Il faut donc essayer de proscrire cette méthode. Le cas le plus horrible est bien sur la modification de la partie que vous avez mis dans chaque vue et ceux sur vos 100 vues. Bonne chance.

Mettre les informations directement dans le controller

Cette technique est un peu plus évolué que la précédente car elle permet d'être plus DRY. En effet, si on a du code entre sa partie "dynamique" et sa vue, on est pas obligé de l'intégrer dans chaque vue. Ce qui permet d'avoir un template plus important et des vues plus légères. Mais l'inconvénient de cette technique et qu'il faut gérer l'affichage et des techniques visuel directement dans le controller. Par exemple le nom des liens, etc.. Ce n'est pas du tout dans la logique MVC, car une partie de la vue est généré et controllé par le controlleur. Le controlleur ne doit que définir quel vue utiliser et donner les variables issues d'une ressources externes.

Utiliser content_for directement dans la vue en utilisant le yield dans le template

Pour que ça soit la vue qui gère le contenu dans le template sans que le controller s'en mêle, la meilleur technique est d'utiliser content_for. Cette méthode permet de mettre en interne un bloc de code HTML. Ce bloc de code HTML n'est lu que par l'utilisation d'un yield :le_nom_du_bloc. On peux ainsi définir le bloc dans la vue et donner sa position directement dans le layout. Si ensuite vous voulez réutiliser le même bloc de code, un render :partial permettra de factoriser encore le code. Voici un exemple d'utilisation de cette méthode avec un template et une vue.

Template :

<html>
  <head>
    <title>;Ma page</title>
  </head>
  <div id="menu">
   <ul>
    <%= yield :menu %>
  </ul>
  </div>
  <p>un peu de texte au milieu</p>
  <div id="content">
    <%= yield %>
  </div>
</html>

Vue :

<% content_for :menu do %>
  <li><% link_to 'Voir', page_url %></li>
<% end %>

<p>Ma vue compléte</p>

Vous trouvez pas ça génial ?

Sinon pour les anciens qui connaissaient la technique avant Rails 2.0 et qui utilisait @content_for_mon_block cette technique est déprécié. Il faut utiliser plutôt le yield depuis la version 2.0.x

[...]
Published on Mar 26 fév 2008 14:02
0 commentaires

RSS