Un premier avis sur Spree (plateforme Ecommerce pour Ruby on Rails)


Depuis bientôt trois ans que je pratique quotidiennement Ruby on Rails, il est toujours resté pour moi une problématique encore non résolue : "et pour le E-Commerce, on fait comment ?". Je dois bien le dire, pour l'instant : "je fais comme je peux". En clair : Prestashop pour les grosses boutiques, et Rails maison pour les boutiques plus modestes mais avec des besoins très particuliers (produits sur mesures, système de promo. avancé...). Quoi qu'il en soit, la conclusion -à ce jour- n'a pas changé : IL FAUT UN MAGENTO EN RAILS.

J'ai bien essayé ForgeOS, en son temps, mais il s'est depuis perdu dans une plateforme beaucoup trop généraliste. Je cherche un sabre laser du E-Commerce, pas un couteau Suisse. Il y a eu aussi substruct... mais là encore, c'est plus "un CMS avec un panier" qu'autre chose, peu de monde semble d'ailleurs avoir suivi.

Nous voila donc fin 2011, et j'apprends que Spree vient de lever 1,5 Million USD, le site Web est tout beau tout neuf et il semble y avoir une communauté derrière. Cool. J'essaye la demo en ligne... allez, je l'installe, et je vois ce qu'il y a dedans...

  • Rails 3.1.1, HAML, SASS/LESS, JQuery. On est vraiment dans ce qui se fait de mieux. En tout cas dans le mainstream de la communauté Rails
  • 55 tables dans la BDD... seulement ??! Pour situer, Prestashop est autour de 135 tables "out of the box", et Magento 218. Bon, ok, ça ne veut pas dire grand chose. Moui, mais bon... quand même, 55 tables, ça "tend quand même à signifier" (notez les guillemets, svp) que pas mal de features seront en add-on, ou bien tout simplement absentes par rapport aux deux autres poids lourds du secteur sus-nommés.
  • Hooo, y'a une API ! Bon signe, ça prouve qu'on est proche des besoins des grosses boutiques.

  • La doc. Ou plutôt : LA doc. Rien à redire concernant ce qu'on trouve sur le site, propre, net, précis (en Anglais, ça va de soit). Ok, mais _ailleurs_ ? Les tutos ? Les Blogs posts ?! Ben... pas grand chose. Quelques bribes éparses sur des forums, à prendre avec des pincettes tellement Spree semble avoir changé ces dernières années mois. "On est dans le cutting edge, man !". En clair : va falloir s'accrocher.

L'installation se déroule facilement, puisque... toute l'application est contenue dans des Gems. Autant le dire franchement : je n'aime pas du tout cette approche (que j'ai déja vu ailleurs :-/). Les Gems, à mon sens (et sauf erreur de ma part, j'ai lu DHH dire la même chose) sont là pour étendre des fonctionnalités à l'échelle de Ruby. Perso, je ne comprends pas qu'on utilise ce moyen pour distribuer toute une appli, qui plus est une appli tournant non au niveau du language, mais bien en dessous dans un Framework ! Concrétement, après installation, vous vous retrouvez donc avec une application... vide, puisque tout est dans des Gems.

Ok, bon, admettons, commençons à modifier une vue ou deux pour se mettre en jambes : que dit la doc ? Qu'il faut créer d'autres Gems pour y mettre sa customisation, même au niveau des simples vues :-/ Donc, si je suis bien tout ça : mon appli est, et restera vide. En fait, Spree, c'est un Framework de Gems, quoi...

Là dessus, j'ai levé la tête du guidon et suis parti à la recherche de boutiques déja montées avec Spree : quelques "something went wrong" (si si) et quelques customisations de vues vraiment simplettes plus tard, j'ai décidé de laisser Spree dans un coin de mon /var/www, et d'y revenir dans quelques mois. Peut-être. Ou plutôt : j'espère.

Ce Post ne représente que ma modeste opinion après quelques heures de survol rapide de Spree. Si vous arrivez à me convaincre de m'accrocher encore un peu avec cette appli, libre à vous d'exposer vos arguments en commentaire, je n'attends que ça ;-)



Commentaires 5 commentaires

Rulu 2011 : la communauté Ruby (on Rails) Européenne vaut vraiment le détour


Un p'tit peu de retard dans la restranscription de RULU, la conf' Ruby (on Rails) Lyonnaise qui a eu lieu le Week-end du 25/26 Juin, mais je tenais à laisser une trace quelque part de cet évenement. Oui, évenement, on peut le dire.

Tout d'abord : la qualité des intervenants

Sven Fuchs (I18n de Rails) Hampton Catlin (Monsieur SASS, HAML), Nick Sutterer (Apotomo, Cells)... j'en passe, et des meilleurs, comme le dit l'expression. J'étais franchement impressionné par le niveau des speakers, surtout pour une première.

Ensuite : la qualité et la diversité des Talks

J'avoue qu'au début, j'avais un peu peur d'être laché par des talks trop orientés technique et "high level". Il n'en fut rien, chaque intervenant prenant soin de rendre son talk réellement vivant, accessible, d'une part. Certains talks étant carrément dans le registre "social", d'autre part (Joshua Wehner par exemple, sur le thème de la nécessaire diversité, pour l'instant absente du milieu Geek).
En bref, je n'ai absolument pas été perdu par d'éventuelles envolées lyriques de techniciens autistes. Bien au contraire même, y compris quand certains thèmes étaient bien épais (le Http Streaming, notamment), j'ai trouvé les intervenants remarquables part leur sens de la pédagogie et de l'écoute.

Ne pas oublier : l'organisation

Un grand bravo à tout le Staff, qui a fait un travail de Titan en très (très !) peu de temps. La participation de l'INSA fut aussi à noter (les locaux étaient juste parfaits). Franck, Damien, Vincent, Camille, Jean Michel (voui, j'en oublie, ne m'en voulez pas)... Vraiment, du bon boulot.

Finalement : la communauté Ruby Européeenne

Un aspect particulièrement intéressant dans ce genre d'évenement à taille humaine (environ 100 personnes), ce sont les échanges ; et de ce côté là c'était aussi, vraiment, un bon moment ! Toulouse, Nantes, Paris, Nice... mais aussi Allemagne, Pays Bas, Suisse ou Angleterre... en ce qui me concerne, j'ai toujours beaucoup de plaisir à m'ouvrir à d'autres points de vue, sortir de mon trop petit monde habituel.
Un dernier petit point que j'ai aussi beaucoup aimé, conséquence directe du milieu dans lequel Rails est le plus utilisé : la communauté regroupe un grand nombre de gens ayant lancé leur business. Beaucoup de "Start-uper" donc, et de nombreux échanges sur comment monter sa boite dans le Net.

Enfin, et je concluerais sur ce point qui ne cesse de m'épater : la communauté Ruby(on Rails) est vraiment une communauté de gens ouverts, intelligents et agréables. Techniquement exigeants, qui ont tous des Macs et ne parlent qu'Anglais, certes, mais des gens qui valent le coup d'être connu. Des gens qui ne se la racontent absolument pas et sont toujours prêt à vous donner un petit coup de main.

Si ça vous tente, et même si vous n'êtes pas (encore) dans la techno pour le moment, passez donc boire une bière (ou deux) au prochain apéro Ruby à Lyon : ce mardi 12 juillet à l'Antre Autre, lyon 1er !



Commentaires Aucun commentaire pour le moment

Redimensionnez vos images à la volée avec Ruby on Rails


J'ai re-factorisé et modifié en profondeur la syntaxe d'appel de mon bon vieux plugin Thumbnailer. Certes, vous pouvez déja redimensionner les images lors de l'Upload avec paperclip, mais thumbnailer vous permet d'aller encore plus loin :

  • Resize à la volé au niveau de la vue
  • Calcul automatique des proportions
  • Gestion automatique du cache, les images ne sont traitées qu'une seule fois par RMagick
  • Possibilité d'appel en "remote", redimensionnez vos images depuis votre client en JS !

Niveau utilisation, on ne peut pas faire plus simple :

# View
<%= thumbnailer :src=>'/images/my_image.jpg', :width=>'200' %>
Et le plugin se charge tout seul de vous générer une image de 200 pixels de large, qui est mise en cache dans '/cache/images/200xauto/my_image.jpg'. La vue finale affichant un tag img comme celui-ci :
<img src='/cache/images/200xauto/my_image.jpg?1305495323' width='200' alt='my_image' />

Tous les attributs possibles d'une balise img sont reconnus, y compris les évenements JavaScript. L'attribut 'alt', si il n'est pas spécifié, sera automatiquement généré à partir du nom de fichier. Vous noterez aussi que le nom de fichier est suffixé par un timestamp, permettant au cache client side de gérer une image différente mais portant le même nom de fichier, tout comme le 'image_tag' original de Rails.

En bonus, avec le paramètre "remote", l'appel de l'image peut aussi se faire directement depuis le paramètre 'src' du tag img :

# View
<%= thumbnailer :src=>'/images/my_image.jpg', :width=>'200', :remote=>true %>

# Final output
<img src='/thumbnailer/200xauto/images/my_image.jpg' width='200' alt='my_image' />

Effet de bord sympathique, vous disposez maintenant d'une simple URL pour appeler une image de n'importe quelle dimension depuis votre client en Javascript, genre :

$('my_image').src='http://my_domain.com/thumbnailer/200xauto/images/my_image.jpg';
alert("Look ! The image has been resized !");

Ca fait maintenant 2 ans que j'utilise ces features dans tous mes projets. Au début c'était une collection de helpers, de routes et de controllers, puis j'ai pris un peu de temps pour packager tout ça dans un plugin. Je pense maintenant que cette nouvelle version est plus clean et efficace, mais je vous laisse vous faire votre avis là dessus. Comme d'habitude, si vous avez des remarques, laissez un commentaire...



Commentaires Aucun commentaire pour le moment

Vous faites quoi le 25/26 Juin ?


Le Week-end du 25/26 Juin se déroulera Ruby Lugdunum, la conf. Lyonnaise autour de Ruby on Rails ! Au programme sont d'ors et déja confirmé Sven Fuchs (Rails Core contributor) et Konstantin Haase (l'un des principaux Developpeur de Sinatra). Il y aura aussi d'autres conf autour de Rubynius, "Solid" application concepts...

L'évenement devrait logiquement se faire sur le Campus de la Doua, et l'ambiance promet d'être -comme toujours avec la communauté Ruby- sérieuse mais sans prise de tête (si si, c'est possible).

Tous les détails sont sur Rulu.eu, et pour rester au courant des préparatifs, le mieux est de s'abonner au compte Twitter.



Commentaires Aucun commentaire pour le moment

SIPS/ATOS et Ruby on Rails avec le plugin 'atos'


Après Paybox, je me suis dernièrement interessé à SIPS/ATOS, poids lourd du paiement ligne hexagonal. Derrière une apparente complexité, le principe est en fait assez simple :

  • L'acheteur valide son panier, un controller récupère les paramètres (prix, id du panier...), les envoie dans un binaire qui crypte le tout et renvoie un formulaire HTML avec 3 (ou +) logos de carte de crédit au sein du site marchand
  • L'acheteur choisi la carte de crédit appropriée et part sur le site de la banque
  • Une fois les numéros de carte validés sur le site de la banque, celui-ci répond au marchand "dans le dos du navigateur" (c'est l'auto-response) via une chaine cryptée
  • un controller récupère l'auto response et la passe à nouveau dans un binaire afin d'en obtenir un tableau associatif

Ne trouvant rien de simple qui me convienne, j'ai codé un petit plugin qui permet de faire tout ça dans Rails très facilement. Dans une console à la racine de votre appli :

script/plugin install git@github.com:gbarillot/atos.git

Ensuite, déposez les fichiers fournis par la banque dans /lib/atos. Le répertoire lib doit ressembler à ça :

/mon_appli
  /lib
    /atos
      /bin
        request
        request_2.4.18_2.96
        ....
      /param
        certif.fr.014295303911111
        parmcom.014295303911111
        parmcom.sherlocks
        pathfile

Petites remarques : le numéro "014295303911111" en suffixe correspond au marchant_id de test, et "sherlocks" correspond au fait que je passe par LCL. Si vous passez par la Société Générale, vous aurez "parmcom.sogenactif". Je préfère vraiment le "conventions over configuration", mais vous pouvez aussi passer les chemins vers vos fichiers au niveau de l'instanciation de la classe Atos. Ca rajoute juste une étape :

atos = Atos.new(
  :root_dir=>'/path/to/your/main/dir'
)
.... et ensuite :
@request = atos.request(
  :merchant_id=>'014295303911111',
  :amount=>'1500', 
  :customer_id=>session[:customer_id],
  :automatic_response_url=>"http://mon_site.com/payment/validate",
  :normal_return_url=>"http://mon_site.com/payment/fr/confirm",
  :cancel_return_url=>"http://mon_site.com"
)

Tant que nous sommes dans le paramétrage des fichiers, déposez aussi le répertoire "logos" et contenant les logos des cartes dans un répertoire public de votre appli (par exemple /public/images/logos). Prenez aussi soin de renseigner le fichier "/lib/atos/param/pathfile" avec tous les chemins __en absolu__ vers les différents répertoires que nous venons de créer

Ok, maintenant que tout est en place, on va pouvoir commencer à faire tourner tout ça. Récuperez l'action de l'acheteur lorsqu'il valide son panier via l'URL de votre choix, et générons la requête. Depuis le controller :

@request = Atos.new.request(
  :merchant_id=>'014295303911111',
  :amount=>'1500', 
  :customer_id=>session[:customer_id],
  :automatic_response_url=>"http://mon_site.com/payment/validate",
  :normal_return_url=>"http://mon_site.com/payment/fr/confirm",
  :cancel_return_url=>"http://mon_site.com"
)

render :template=>'payment/call_request'

Si tout se passe bien, nous récupérons dans @request un formulaire HTML avec les logos des cartes, ainsi qu'une variable "DATA" dans un champ "hidden" contenant l'intégralité de notre requête cryptée, il n'y a plus qu'à l'afficher dans le template (ici avec HAML) :

%span
  = "Sélectionnez votre type de carte :"
%br
= @request

------------ L'acheteur clic sur un des logos de carte et se rend sur le site de la banque. Celle-ci va maintenant nous répondre ---------------------

On récupère l'auto-response sur une URL à l'écoute en POST (je vous laisse créer la route de votre choix, dans mon exemple, c'est /payement/fr/validate). Il n'y a que 2 lignes à ajouter dans le controller approprié :

      
response = Atos.new.response(datas)

response[:response_code] # 00 => transaction réussie
...

Et hop, on obtiens un joli Hash avec toutes les variables de réponse disponibles dans l'API (voir le "dictionnaire des données" fourni avec l'API pour tous les détails). Maintenant, à vous de traiter cette réponse selon que le paiement a été accepté ou refusé, puis de valider l'achat dans la Base...


Quelques petits détails :

  • les 6 paramètres que j'utilise dans mon exemple au niveau de la requête sont les seuls à être requis par le plugin, mais vous pouvez tout à fait envoyer tous les paramètres stipulés dans le "dictionnaire des données", rajoutez simplement les couples "clef/valeur" dans le hash de la requête.
  • Par défaut la langue et la devise utilisés sont "fr/euro", mais vous pouvez surcharger avec ceux de votre choix au moment de l'instanciation de la classe Atos.
  • Les URL de retour (normal/cancel) sont envoyées par POST, n'oubliez donc pas d'écouter aussi en POST les routes correspondantes
  • C'est idiot mais ne pas oublier de lever la protection CSRF pour l'auto response (par rapport à mon exemple, ce serait "protect_from_forgery :except=>:validate"). Sans quoi l'auto-response ne sera jamais recevable par votre controller. C'est c** mais ça m'a couté 30mn d'arrachage de cheveux :-/.

Vous pouvez m'envoyer un Mail si vous avez des problèmes, je ne garantie rien, mais j'essaierai de répondre.



Commentaires 2 commentaires