jeudi 28 juillet 2011

Tester son code Ruby : Minitest



la programmation est une activité super intéressante. Chacun a sa métaphore préférée qui explique ce que signifie pour lui la programmation. Eh bien, pour moi "la programmation est tout au  sujet d'automatisation". 

Vous êtes devant votre ordinateur pour lui apprendre à faire automatiquement un travail que vous savez faire, mais que vous ne voulez pas faire encore et encore.

Quand on s'en rend compte, on cherche tout de suite des choses qui  peuvent être automatisées. Je n'aime pas me répéter encore et encore et encore. C'est ennuyeux et parfois énervant!
 Eh bien, il y a une tâche particulière qui est liée à la programmation et qui se répète tout le temps : "vérifier que votre logiciel fonctionne!" Donc une tâche à automatiser.

 > MINITEST 

Heureusement pour nous, Ruby a des outils fantastiques qui vous permettent de mettre en place des tests pour votre code que vous pouvez exécuter automatiquement. Vous pouvez vous éviter de perdre du temps et de l'effort en laissant l'ordinateur exécuter des milliers de tests à chaque fois que vous modifiez votre code. Je ne vais pas disserter sur les vertus du«Test Driven Development" dans cet article, mais écrire les premiers tests. Pour commener, nous allons prendre un petit peu de code pour travailler, et je vais vous montrer comment le tester en utilisant minitest.

Pour cet exercice, nous allons faire quelque chose de simple et nous concentrer sur les tests. Nous allons écrire une classe Ruby appelée Membre. Il va falloir un tas de fonctionnalités, mais voici les deux premières méthodes, nous aurons besoin:
-> un membre peut ajouter d'autres membres en tant qu'amis-> un membre peut savoir combien d'amis il a-> quand il est nouveau, le nombre de ses amis est 0-> quand il supprimer sa liste d'amis, il revient à 0 ami.
Très simple non ? Pour écrire ces tests nous allons utiliser une librairie Ruby appelée minitest. Elle est native dans Ruby1.9 mais si vous utiliser 1.8 installez la en faisant :
> gem install minitest
Ecrivons notre premier test !

require 'minitest/autorun'

class TestMembre < MiniTest::Unit::TestCase
  def setup
    @membre = Membre.new
  end
  def test_pas_d_amis
    assert_equal 0, @membre.nombre_amis
  end
end

Ok! Il ya beaucoup de choses ici. Prenons ligne par ligne. Sur la première ligne, nous avons un «require». La partie 'minitest/autorun' comprend tout ce dont vous avez besoin pour exécuter vos tests, automatiquement. 
Tout ce dont nous avons besoin pour faire tourner nos tests est de taper "ruby membre.rb". Mais regardons le reste du fichier avant de faire cela. La prochaine chose que nous faisons est écrire une classe qui hérite de l'une des classes de base de minitest. Voilà comment fonctionne minitest, en exécutant une série de TestCases. Minitest permet également les tests de groupe et en plusieurs fichiers.
Dans notre TestCase nous avons 2 méthodes : setup et test_pas_d_amis. La méthode setup est exécutée automatiquement et avant chaque test. Elle permet de préparer le terrain pour réaliser les tests. La deuxiéme méthode permet de vérifier qu'un nouveau membre n'a pas encore d'amis.
Lançons notre test et voyons ce que ça donne :
> ruby membre.rb

Loaded suite membre
Started
E
Finished in 0.000853 seconds.

1) Error:
test_pas_d_amis(TestMembre):
NameError: uninitialized constant TestMembre::CashRegister
membre.rb:5:in `setup'

1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

Test run options: --seed 36463
Waaaaw cool ! Comme vous pouvez le voir nous avons un test et un échec. Nous savons que les classes Ruby sont des constantes et il en manque une ici. Ecrivons cette classe alors.
class Membre
end

Relançons le test :

1) Error:
test_pas_d_amis(TestMembre):
NoMethodError: undefined method `nombre_amis' for #<Membre:0x00000101032a80>
membre.rb:9:in `test_pas_d_amis'

ça avance ! et cette fois ça nous dit qu'il manque une méthode.

class Membre
  def nombre_amis
  end
end
Relançons le test encore une fois.

1) Failure:
test_pas_d_amis(TestMembre) [membre.rb:9]:
Expected 0, not nil.
Erreur claire : On s'attend à 0 pas à nil

def nombre_amis
  0
end

Ok cool. Le test passe mais notre total est toujours fixe (0). Vérifions que quand on ajoute des amis, le nombre d'amis change.

def test_calculer_nombre_amis
  @membre.ajouter 1
  @membre.ajouter 2
  assert_equal 3, @register.nombre_amis
end
A ce stade, la visoin doit être un peu plus claire pour vous. Lançons nos tests encore une fois


Loaded suite membre
Started
.E
Finished in 0.000921 seconds.

1) Error:
test_calculer_nombre_amis(TestMembre):
NoMethodError: undefined method `ajouter' for #<Membre:0x00000101031838>
membre.rb:13:in `test_calculer_nombre_amis'

2 tests, 1 assertions, 0 failures, 1 errors, 0 skips

Test run options: --seed 54501
Ok! vous voyez le ".E" sur la 3iéme ligne du résultat ? Ben ça veut dire qu'on a eu 2 tests, un réussi '.' et un échoué "E".
Ajouter la méthode qui manque et continuons .


def ajouter(ami)
  @amis << ami
end


Oups ! le @amis n'a pas encore été défini :) Lancez le test et il vous le dira.



def initialize
  @amis = []
end
Avec ce constructeur, nous n'aurons plus ce genre de problèmes.


Relancez le test et vous aurez une erreur : le nombre d'amis est toujours 0 alors qu'il devait passer à 3 .
Corrigeons ce petit souci:



def nombre_amis
  @amis.inject(0, &:+)
end

C'est fait. Alors pour vérifier que vous avez bien compris le truc, écrivez le dernier test : supprimer_liste_amis.


.....


Alors c'est quoi l'intérêt d'écrire les tests en premier ? Ben ça vous permet d'écrire le code qu'il faut pour répondre aux spécifications que contient votre cahier de charges d'une part et de vous assurer que votre logiciel fait exactement ce pour quoi il a été écrit. 


Les mises à jour du code deviennent chose simple. Et quand il a un problème on sait que c'est le nouveau code qui a cassé quelque chose surtout que le "code base" était digne de confiance.


Dans la suite de cette série d'articles sur les tests, nous allons intégrer les tests à des applications Rails et Sinatra.






mardi 19 juillet 2011

Rails Admin

Salut !!!!

Pas la peine de chauffer vos méninges en cherchant des tutos pour installer Rails Admin dans vos applications Rails.

je l'ai fait pour vous.

Créons une petite application Rails ,et ajoutons a cette merveille une autre merveille: l'interface d'administration.

Pour ce faire nous utilisons:

  • rails 3.0.9
  • rails_admin 0.0.1 (version actuellement présente sur github)
  • ruby 1.9.2

commençons par créer notre projet

$rails new railsAdminProject
$cd railsAdminProject

éditons le fichier Gemfile de notre application
$vim Gemfile

et ajoutons les gems nécessaires
gem 'devise'
gem 'rails_admin', :git => 'git://github.com/sferik/rails_admin.git'

installons les dépendances / gems de notre application :
$bundle install

Pour avoir le mode d'utilisation du générateur de rails_admin, faire un listing de tous les générateurs intégrés à notre application.
$rails generate

à la fin du listing des générateurs nous retrouvons ceux de rails admin.
RailsAdmin:
rails_admin
rails_admin:install_migrations
rails_admin:uninstall_migrations

exécutons le générateur de rails admin:
$rails generate rails_admin

une suite d'instruction apparaît, spécifiant comment installer rails_admin:
$rake rails_admin:install

créons les tables en base de données, nécessaire a l'application rails_admin.
$rake db:migrate

démarrons le serveur
$rails server

Sur la barre d'adresses sasire l'URL: http://localhost:3000/admin. Vous êtes redirigé vers la page de login.

Jusqu'ici aucun utilisateur n'est enregistré pour l'administration, donc faut s'enregistrer (sign up) en renseignant les informations demandées (email,password, confirmation de password).

BINGOOOO !!!!!. vous y êtes, dans l'interface d'administration Rails_admin de votre application.

Tests du fonctionnement de l'interface d'administration.

En utilisant le générateur scaffold, ajoutons la gestion des produits à notre application rails

$rails generate scaffold Produit nom:string details:string

générons les migrations nécessaires au modèle Produit
$rake db:migrate

Allons sur l'interface d'admninistration(http://localhost:3000/admin) rails_admin, nous avons une onglet pour la gestion des Produits.

BANG !!!! vous pouvez administrer vos produits, et tous les modèles que vous ajoutez a votre application RoR.

Bon heiiinnn !!!!. je vous laisse découvrir les fonctionnalités de Rails_admin. C'est trop cool !!!.

A une prochaine fois. Si je découvre d'autres choses sur Rails Admin je vous ferai signe.

A plus !!!!!.

Ecrire un DSL en Ruby

Bonjour,


Je m'excuse de pas avoir publié cet article hier ( le lundi ) comme le veut la coutume :) J'étais dans l'embarras du choix du sujet à aborder cette semaine. Et vu que je suis en train de développer une API pour un domaine assez "spécifique" qui a son propre jargon j'ai (enfin) eu une idée : comment écrire un jargon en Ruby.
Dans le monde de l'informatique un jargon est dit DSL.
Les DSL et Ruby
Ruby fournit quelques fantastiques fonctionnalités natives pour la création Domain Specific Languages ​​(DSL). Un Domain Specific Language est comme un langage de programmation écrit pour un domaine déterminé. C'est une façon d'exposer les fonctionnalités dans unformat simple et lisible pour les autres programmeurs (ou vous-même). Un des DSL les plus couramment utilisés dans le monde Ruby est Sinatra.



require 'rubygems'
require 'sinatra'

get '/hello' do
  "Hello world."
end
Sinatra est un DSL pour créer des applications web. Sa syntaxe est construite sur la base des verbes HTTP tels que GET, POST, et PUTEn exposant les fonctionnalités de cette manière, le code est beaucoup plus lisible et beaucoup plus parlant surtout quand on sait comment fonctionne le web en général.


un peu de Yield 

yield est un concept très important à comprendre pour réussir à créer un DSL Ruby. La fonctionnalité fournie par yield permet à un développeur de faire passer le contrôle temporairement pour permettre l'éxécution d'un autre bout de code. Si vous avez déjà utilisé le Array#map (ou Array#collect) qui est un exemple intéressant de l'utilisation de yield. 


[1, 2, 3].map{|i| i + 1} # => [2, 3, 4]
Alors comment pourrions-nous ré-implémenter la fonctionnalité carte si ce n'était pas fait pour nous? C'est en fait assez simple en utilisant yield :

class Array
  def my_map
    resultat = []
    self.each do |truc|
      resultat << yield(truc)
    end
    resultat
  end
end

[1, 2, 3].my_map{|i| i + 1} # => [2, 3, 4]
yield arrête essentiellement l'évaluation(éxécution) de la méthode et évalue le bloc passé, l'appelant avec les arguments fournis dans la déclaration de yield lui-même. Donc, si j'avais une méthode qui simplement retournait  ce qu'on lui passe en arguments, ça ressemblerait à ça :


def confesser( argument )
  yield argument
end

confesser(" Ruby c'est magnifique !") do |arg|
  puts arg
end

# Sortie : "Ruby c'es magnifique !"
Yield et les DSLs


Maintenant, en utilisant yield, nous avons les bases pour créer un DSL simple. Je sais pas pour vous mais moi j'ai faim ! Donc nous allons créer un DSL pour décrire les recettes de cuisine. Nous voulons être en mesure de créer des recettes, d'ajouter des ingrédients ainsi que les étapes, et avoir un joli affichage de tout ça.  Au boulot now :



class Recette
  attr_accessor :nom, :ingredients, :instructions

  def initialize(nom)
    self.nom = nom
    self.ingredients = []
    self.instructions = []
  end

  def to_s
    affichage = nom
    affichage << "\n#{'=' * nom.size}\n\n"
    affichage << "Ingredients: #{ingredients.join(', ')}\n\n"

    instructions.each_with_index do |instruction, index|
      affichage << "#{index + 1}) #{instruction}\n"
    end

    affichage
  end
end

Now ajoutons une recette :


plat = Recette.new("Omelette")

plat.ingredients << "Oeufs"
plat.ingredients << "beurre"
plat.ingredients << "fromage"
plat.ingredients << "autres trucs "

plat.instructions << "Beurre dans poêle"
plat.instructions << "ouefs ..."
plat.instructions << "fromage ..."
plat.instructions << "la suite certainement ..."

Now faisons un "puts plat"! ça doit donner :


Plat
====

Ingredients: Oeufs, beurre, fromage, autres trucs

1) Beurre dans poêle
2) ouefs ...
3) fromage ...
4) la suite certainement ...

Bien que cela fonctionne, le code ne semble pas être élégant! Nous avons besoin d'un moyen de faire ressembler à ce qu'on peut voir sur une carte de recette. Rendons le code un peu plus beau. Pour commencer, nous allons réécrire le constructeur et yield :


def initialize(nom)
  self.nom = nom
  self.ingredients = []
  self.instructions = []

  yield self
end

Next, nous devons ajouter quelques méthodes pour ajouter des ingrédients et des instructions à la recette :


def ingredient(nom, options = {})
  ingredient = nom
  ingredient << " (#{options[:quantite]})" if options[:quantite]

  ingredients << ingredient
end

def instruction(texte, options = {})
  etape = texte
  etape << " (#{options[:pendant]})" if options[:pendant]

  instructions << etape
end

Cela nous permet de créer une recette d'une manière beaucoup plus naturelle :


nouilles_au_fromage = Recette.new("Nouilles au fromage") do |r|
  r.ingredient "Eau",      :quantite => "2 verres"
  r.ingredient "Nouilles", :quantite => "1 verre"
  r.ingredient "Fromage",  :quantite => "3 cuillères"

  r.step "L'eau sur le feu",      :pendant => "5 minutes"
  r.step "Ajouter les nouilles.", :pendant => "6 minutes"
  r.step "Enlever l'eau."
  r.step "Mélanger le fromage aux nouilles."
end

"puts nouilles_au_fromage" donnera :


Nouilles au fromage
===================

Ingredients: au (2 verres), Nouilles (1 verre), Fromage (3 cuillères)

1) L'eau sur le feu. (5 minutes)
2) Ajouter les nouilles. (6 minutes)
3) Enlever l'eau.
4) Mélanger le fromage aux nouilles.

Et voilà ! le petit déjeuner est servi. 
Nous verrons dans la suite comment rendre ce DSL plus joli et plus proche du langages des chefs cuisiniers.


Conclusion :
Nous avons appris à écrire un DSL en Ruby et nous n'avons utilisé qu'une seule méthode ( Yield ). Dans la suite de cet article nous utiliserons d'autres merveilles de Ruby.


Bonne journée

lundi 11 juillet 2011

Unitialized constant Rake....

Salut tout le monde euh c'est moi....
Bon si suis la c'est juste pour donner une astuce relative à cette erreur lorsque vous essayez de faire un rake db:migrate ou un rake db:create, Bah il semblerait que le fait de mettre à jour rake à la version 0.9.2 pose un certain nombre de soucis....
Bon bon voici la solution si vous utilisez rake 0.8.7 faites un bundle rake update et passer à la version 0.9.2, ensuite allez éditer votre rakefile et ajouter ceci :

require 'rake'
require 'rake/dsl_definition'
module ::Nom_de_votre_application
class Application
include Rake::DSL
end
end
Nom_de _votre_application::Application.load_tasks

et voila le tour est joué
bon ben c'etait moi....:-)

mardi 5 juillet 2011

Sinatra au meetup DakarLUG ce samedi 09 juillet


Introduction à Sinatra au meetup DakarLUG ce samedi 09 juillet suivie d'un atelier pour écrire une première vraie application web avec Sinatra munie d'une API REST.

lundi 27 juin 2011

Authentication System : part 2

Bonjour,


Dans la première partie de cet article, nous avons vu comment chiffrer les informations de connexion d'un utilisateur avant de les stocker dans la base de données; et nous avions une méthode login qui nous permet de comparer des signatures de mots de passe. Donc nous avions un systéme de SignUp/SignIn assez utilisable mais qui reste indépendant de notre application. C'était le but c'est vrai. 
Aujourd'hui nous allons utiliser ce système pour sécuriser notre application.


On veut que seules les pages d'accueil et de connexion soient accéssibles aux gens pas encore connectés. Et pour celà nous allons utiliser ce qu'on appelle des filtres. 
Les filtres sont des .......... voir wikipedia :)



class AppController < ApplicationController

  before_filter :logged_in, :except => [:index, :login]

  def index
     # ....
  end
  
    # ... la suite du contrôleur
end

Une fois que Rails voit le before_filter dans notre contrôleur, il effectue plusieurs choses : passer la main à la méthode appelée ( logged_in dans notre cas ) et attend que cette méthode lui donne une réponse claire : True ou False.

Une fois que la réponse est là, il lit le reste du bloc de code et l'exécute.

Nous remarquerons certainement que la méthode logged_in n'a pas encore été définie. Alors où est ce qu'on doit la définir ? dans un endroit où elle sera accessible par toutes les entités de notre application : contrôleurs et vues. Nous verons pourquoi plus tard inchaallah.


class ApplicationController < ActionController::Base


  helper_method :connected?, :logged_in


  protected 
  
  def connected?
return true if session[:utilisateur]
false
  end 
  
  def logged_in
if !connected?
redirect_to login_path 
flash[:message]= " Désolé ! Accés refusé"
    end
   
  end
end



Du nouveau ! En plus de l'utilisation de méthodes privées nous avons utilisé une nouvelle méthode : helper_method


Alors que fait cette méthode ? 


Elle permet de rendre disponible une méthode dans le scope de vues ! C'est tout ce que nous avons besoin de dire et de savoir à ce stade.


Et maintenant dans nos vues on peut s'amuser à faire : 


<% if logged_in %> 
   Bonjour
<% else %>
  <%= link_to " connexion ", login_path %>
<% end %>


Merci et bonne semaine.

vendredi 24 juin 2011

Le rendez-vous des experts: Ruby On Rails





  Une introduction à Ruby On Rails !

Le framework qui continue de révolutionner le monde du web présenté par un étudiant de SUPINFO France. Il essaie de couvrir tout ce qu'il faut savoir pour démarrer .

Authentication system for Rails applications



Bonjour,


Aujourd'hui on va parler d'un problème que nous rencontrons à chaque fois que nous devons développer une application web avec un accès contrôlé.
Je veux dire par "accès contrôlé" que nous avons besoin d'être authentifié pour pouvoir effectuer certaines opérations.


Nous avons besoin de savoir qui fait quoi ! Ce qui nous pousse à protéger certaines sections de notre application supposées être réservées aux membres.


Pour réaliser une telle tâche on a souvent recours aux "solutions" prêtes. Ces solutions sont souvent des gems/plugins.
L'avantage de ces solutions c'est qu'elles ont été testées et améliorées par des milliers de programmeurs.


Leur plus grande faiblesse est que souvent elles ne sont pas faites pour vous spécialement. Ce qui rend la personnalisation de ces solutions un peu difficile. Car pour modifier le workflow défini par défaut il faut avoir une très bonne connaissance du langage Ruby pour éviter de faire du n'importe quoi et aussi savoir comment les plugins Rails sont conçus.
Nous n'allons pas entrer dans ce sujet car trop vaste et c'est un peu tôt pour nous de l'aborder.


Alors ! Et si on veut développer notre propre solution, comment faire ?


Une solution d'authentification doit être sûre, évolutive et facile à modeler. Et pour ce faire elle doit être totalement indépendante du reste de l'application.


Je vais partager avec vous ma façon de faire. Elle est très simple. Elle consiste en l'enregistrement de la signature du mot de passe et de la clé utilisée pour chiffrer. Donc les mots de passes enregistrés dans la base de données sont indéchiffrables en cas d'attaque sur votre serveur de bases de données.


The Model


Pour utiliser ce modéle dans vos applications, vous aurez juste besoin d'avoir les attributs suivants : login, hashed_password et salt qui représentent l'identifiant de l'utilisateur, le mot de passe crypté et la clé de cryptage.





Et le processus de création d'un nouveau compte reste le même !
 Utisateur.create(:attributs)

The controller


Et dans mon contrôleur j'ai mes méthodes de login et de logout.





The view


A ce stade nous avons un systéme de login/logout et création d'un nouveau compte utilisateur avec cryptage de mots de passe. Cette solution est très simple facile à embarquer dans toutes vos applications Rails.



mercredi 8 juin 2011

Understanding Rack 2 : les middlewares

Bonjour,


Aujourd'hui, à mon réveil, j'ai senti une envie folle de coder. Donc après avoir pris ma douche, prié et pris mon petit déjeuner ( j'aurais pu vous inviter ! je sais ), je suis entré dans mon repertoire "Projets" et je suis tombé sur "Rack applications" et là je me suis rappelé que je vous dois la suite de la série "Understanding Rack" que j'ai commencée il y a quelques semaines déjà.


L'épisode 1 de cette série introduit Rack, son utilité et ses bases. Je vous conseiller de le lire avant de continuer avec cet article.


Dans cet épisode nous allons savoir ce qu'est un middleware Rack, à quoi il sert, comment en créer et surtout comment l'utiliser dans une application en production (ou en dév).


Rack middleware ?


un middleware rack est "juste" une application Rack qui a connaissance de l'existence d'autres applications Rack. J'explique ! Quand un middleware rack est invoqué, il peut passer la main à d'autres middlewares/applications pour des traitements spécifiques.


Exemple par le code :


module Rack
   class MonMiddleware
     def initialize(app)
       @app = app
     end
     def call(env)
       if @app
         status, headers, body = @app.call(env)
       else
         [ status, header, body ]
       end
     end
   end
end


Le code est assez simple et clair. Nous avons une application Rack qui "peut" passer la main à une autre application si cette dernière utilise ce middleware.


Donc, en résumé, un middleware Rack est une application utilisable par les applications Rack. Oui ! c'est tout ! ( pour le moment ).


Et pour donner un peu plus de "valeur" ou d'importance aux middlewares, nous allons parler de Rack::Restrictor.


un peu d'histoire !


Il y a quelques mois, pour le compte du SUP'Management Mauritanie,  j'ai dû écrire un petit middleware pour protéger certaines sections de leur SI.
Ils ont en place une application ( Rails ) appelée RubyCampus qui leur permet de gérer leurs étudiants, les enseignants, la paie, la gestion des examens et tout le tralala. Evidement ces modules ne sont pas tous développés par la communauté RubyCampus.


Le problème !


Après quelques mois d'utilisation ils se rendent compte qu'ils doivent restreindre l'accès à certaines parties de l'application à "leur équipe" d'informaticiens. Mais comment le faire ? Avoir deux  sous-applications : une pour les étudiants et une pour l'administration ? comment s'assurer que les étudiants ne pourront accéder qu'à "leur" application ?


la solution adoptée !


Pour régler ce problème, on a proposé que le staff devant accéder à la partie Admin soit dans un réseau et que seules les machines dans ce réseau pouvaient avoir accès à la section en question.


Mettre en place un tel réseau est chose aisée certainement ! Now la partie logicielle! 
La solution a été un middleware appelé Rack::Restrictor que vous pouvez télécharger ici. Il permet de spécifier la plage d'adresses ip acceptées et il se charge du reste.


Très simple comme solution mais ça marche.


voici le code :



Ok cool ! mais comment utilise-t-on un middleware Rack ?


Simple ! On va utiliser les fonctions du Rack::Builder !
( VOUS( certainement ) :hé ho c'est quoi Rack::Builder ? ... 
  Moi : on en reparlera plus tard )


Rack::Builder n'a que trois (3) méthodes : map, use et run.


Revenons à notre sujet. Créons une petite applicaton Rack et appelons notre middleware.



   class MonApp

     def call(env)
       status = 200
       headers= { "Content-Type" => "text/plain" }
       body   = "Bonjour tout le monde"
       return [ status, headers, body ]
     end

   end

Là nous avons une application très simple qui renvoie tout simplement une chaîne de caractéres. Mais notre application a besoin d'être sécurisée et réservée à très peu de personnes :)

pour ce faire nous allons utiliser Rack::Restrictor qui installable par " > gem install rack_restrictor ". 

   require 'rack_restrictor'


   use Rack::Restrictor, "192.168.0.1/24" 
   run MonApp.new


Ce que ça fait ! On require la gem, on appelle le middleware, on lui passe la plage que nous voulons autoriser et à la fin on lance notre application. 


PS : il faut toujours appeler votre application en dernier et prétez attention à l'ordre dans lequel vous appelez vos middlewares.


Lancer votre code et testez ! 


Je vais parler de Rack::Builder et comment embarquer des middlewares/applications Rack dans des applications web plus sérieuses écrites en utilisant Rails, Sinatra ou autre.


à plus

lundi 6 juin 2011

Rhodes ...


Coucou ça faisait un moment pour ne pas dire une éternité...
Entre plein de trucs à faire et pas de journées de 48h comprenez mon absence...
Aujourd'hui je vais vous parler aussi de mobile, pas de Haml, Hassane m'a précédé mais plutôt d'une solution à une problématique majeure.

Vous travaillez dans une entreprise ( ou pas :) ) et on vous demande de développer une application pour smartphone tournant sous IOS, Androïd, et pire on peut même vous obliger à le faire sous Windows Mobile ( sans rancune... ). Que faire ? Développer la même application sur toutes ces plateformes, c'est à dire effectuer le même travail sur autant de plateformes ? se suicider ? ( c'est une option oui ) ou encore faire du web mobile ?

Bah rassurez vous il y a une autre solution et c'est un framework basé sur ruby qui respecte de façon séduisante le principe du DRY ( Don't Repeat Yourself ), ce framework c'est Rhodes, et il permet de developper une fois son application et de Run Everywhere, il suffit juste de specifier la plateforme cible. Si si c'est bien possible!

Rhodes est un framework opensource basé sur le langage ruby qui permet de construire rapidement des applications natives en html et ruby pour la majeure partie des systémes d'exploitation des smartphones.
Rhodes integre par défaut les layout des différentes vues des smartphones et se charge d'adapter le layout au smartphone cible, la logique de rhodes est basée sur une architecture MVC tres proche de rails.

Rhodes intégre un web server, et utilise le browser control des systemes d'exploitation des smartphones afin de permettre au développeur d'ecrire du html et d'editer ses templates, toutefois l'utilisateur final n'a pas connaissance que c'est son browser qui est derriére le rendu de l'application qu'il utilise.
Aussi Rhodes n'est pas venu tout seul, il est accompagné de RhoSync qui est un sync server, un serveur séparé qui se concentre sur les web services, et permet de syncrhoniser les données avec votre application. Si vous êtes dans ce type de problématique RhoSync peut être votre solution.

Toutefois cela ne signifie pas que vous êtes dans l'obligation d'utiliser RhoSync pour synchroniser vos web services avec les données de votre application....vous pouvez en effet développer votre propre serveur et votre propre client pour la synchronisation de vos web services
Et voila comment éviter un suicide collectif .... :)

Pour en savoir plus => http://rhomobile.com
ou encore