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.
[...]Pictrails 0.1.0 sortie pour une première alpha
Ca y est, j'ai enfin sortie une première version de Pictrails.
Pictrails est une application réalisé avec Rails 2.0. Elle permet de gérer des albums photos.
Pictrails est venue du constat qu'aucune application libre réalisé avec RubyOnRails n'était plus à jour sur la création d'une galerie personnel de photo. Il existe bien des sites internet qui fournissent ce service comme Flikr, mais cela pose la question de la diffusion de ses données. Grâce à des applications libre comme Pictrails, vous êtes le seuls maitre de vos données.
Actuellement Pictrails est encore en alpha. Il n'y a aucun test unitaire de réalisé dessus ce qui peux entrainer de grosses erreurs. Je vais immédiatement réaliser tous ces tests pour que la prochaine version ait une couverture de code de 100%
Toutes personnes souhaitant contribuer à ce projet est la bienvenue. J'ai mis en place un projet sur mon redmine personnel pour gérer pictrails. Vous pouvez y poster des bugs ou améliorations que vous souhaitez. Un repository mercurial est lui aussi en place pour le contrôle de source. Ma plus grosse difficultés étant le graphisme, toutes propositions est la bienvenue.
[...]script/generate directement dans svn
A chaque fois que j'utilisais le script de génération de code de Ruby On Rails, je devais lancer ensuite un ajout des sources dans subversion avec un petit svn add.
Mais voilà, je viens de découvrir que cette commande est tout à fait inutile. En effet, le script de génération comprend une option qui nous permet d'éviter ce genre de manipulation inutile. Il y a l'option -c.
$ ./script/generate migration -c change_type_format
exists db/migrate
create db/migrate/030_change_type_format.rb
A db/migrate/030_change_type_format.rb
J'adore l'implémentation de Subversion dans Ruby On Rails
[...]Un script pour tester votre application pour Rails 2.0
Mislav Marohnic a réalisé un petit script Ruby pour tester si votre application Rails valide 1.2.3 l'est aussi pour la prochaine migration à Rails 2.0 (attendu avec impatience). Ce script fait une vérification de toutes les alertes (warning) que vous avez concernant les méthodes déprécié (deprecated)
Pour tester ce script, il suffit de lancer la commande suivante quand vous êtes dans le dossier de votre application :
wget http://pastie.caboo.se/99900.txt?key=krcevozww61drdeza13e3a -q -O- | ruby -
Sinon vous pouvez aussi regarder les sources
source issue de : Peter Cooper
[...]Deployer un blog Typo grâce à Capistrano2
Voulant utiliser capistrano2 et mettre en place un blog Typo, j'ai décidé de déployer mon blog Typo grâce à Capistrano2. Je vais indiqué ici toutes les étapes que j'ai effectuées. Ce post aura ainsi un double intérêt.
- Expliquer comment deployer une application Typo avec Capistrano2
- Expliquer par l'exemple d'une utilisation de Capistrano2
Pour commencer Capistrano2 est vraiment très dépendant d'un système de versionning. Dans mon cas j'ai utilisé le dépôt subversion de Typo et comme je voulais utiliser leur version 4.1, j'ai récupérer l'url suivante qui est le tag de la version 4.1:
http://svn.typosphere.org/typo/tags/release_4_1/
Préparation de l'application à déployer
Préparation en local
Il faut commencer d'abord par faire un checkout complet de la version que l'on désire déployer. Ca permet surtout d'avoir une sorte de miroir de la version qui sera sur le serveur et ainsi faire des modifications sur cette version pour testé et ensuite les déployer sur le serveur.
On va maintenant commencer à créer un projet capistrano2. Pour cela, il suffit d'aller à la racine du répertoire de checkout et de lancer la commande :
capify
Grâce à cette commande le fichier config/deploy.rb est crée. C'est lui qui nous permettra de définir la configuration de notre application sur le serveur distant. Le fichier Capfile est lui aussi crée à la racine et il permet d'ajouter des tâches. Il suffit de le considérer comme une sorte de fichier de RakeFile.
Voici ce que j'ai mis dans mon fichier deploy.rb. Bien sur, il n'y avait pas ces informations à la base
set :application, "typoblog-dev"
set :repository, "http://svn.typosphere.org/typo/tags/release_4_1/"
# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
set :deploy_to, "/var/rails/#{application}"
# If you aren't using Subversion to manage your source code, specify
# your SCM below:
#set :scm, :subversion
role :app, "shingara.fr"
role :web, "shingara.fr"
role :db, "shingara.fr", :primary => true
Voici une explication de chaque champs
- set :application => Défini le nom de l'application qu'on va être déployé. C'est surtout utilisé pour le nom du répertoire de déploiement.
- set :repository => le chemin du dépôt Subversion qui sera récupéré lors du déploiement.
- set :deploy_to => Défini le répertoire sur le serveur distant où seront placés les sources de l'application
- set :scm => Le type de système de versionning qui permettra de récupérer les sources. Par défaut il s'agit de subversion.
- role :xxx => permet de définir les serveur où seront chaque rôle. serveur web, mysql et fichier. Dans mon cas il s'agit du même serveur.
Il ne reste plus qu'à voir pour le fichier Capfile, mais je le ferais dans un second temps.
Préparation sur le serveur
Il faut penser à préparer la base de donnée qui recevra les informations de notre blog. Il faut donc que la base et les accès soient prêts. C'est la seule manipulation réelle à effectuer sur le serveur.
Déploiement
On pourrait faire simple pour déployer notre application et faire ainsi :
$cap deploy:setup $cap deploy:migrations
La première tâche permettant de préparer le terrain en créant les répertoires de base. La deuxième permettant que :
- les sources soient déposées sur le serveur distant
- rake db:migrate soit lancé
- le serveur est lancé en fastcgi
Mais voilà, rien ne fonctionnera, car il n'y a pas de fichier database.yml sur le serveur car il n'existe pas sur le dépôt subversion. Il va donc falloir en ajouter un sur le serveur.
Création de tâches personnalisées
Voici le fichier CapFile que j'ai ainsi créé.
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
load 'config/deploy'
after 'deploy:symlink', 'deploy:upload_database_config'
after 'deploy:symlink', 'deploy:upload_mongrel_cluster'
namespace :deploy do
desc 'Upload the config database file in release path'
task :upload_database_config do
#Define a database file
database = {'production' => {
'database' => 'typo',
'adapter' => 'postgresql',
'host' => 'localhost',
'username' => 'xxxx',
'password' => 'xxxx'
}
}
#upload
put database.to_yaml, "#{current_path}/config/database.yml", :mode => 0444
end
end
Dans ce fichier j'ai ainsi créé une nouvelle tâche. Cette tâche me permettra de créer un fichier database.yml sur le serveur et ainsi en avoir un spécifique à mon serveur. J'ai aussi défini que cette tâche sera toujours lancée après la tâche deploy:symlink. Tâche qui est réalisée lors de la tâche deploy.
Pour créer la tâche d'envoi sur le serveur du fichier database.yml, j'ai utilisé la méthode "put" de Capistrano. Elle se base sur le système de connexion au serveur pour envoyer des fichiers dessus. Avec la variable #{current_path}, j'ai pu définir le chemin vers le dossier contenant les sources utilisées pour lancer l'application.
Pour définir que cette tâche se lance après une autre tâche Capistrano, il suffit tout simplement d'appeler la méthode after.
Ca y est maintenant si vous relancez toute la procédure que je vous ai indiquée précédemment avec les tâches Cap vous aurez votre application qui démarrera avec FastCGI.
Et avec Mongrel_Rails et Nginx
Personnellement, je ne passe pas par FastCGHI, j'utilise mongrel_rails et Nginx. Donc voici les modifications que j'ai réalisées pour que tout passe de la même manière.
J'ai tout d'abord ajouté des tâches Cap:
after 'deploy:symlink', 'deploy:upload_mongrel_cluster'
namespace deploy do
desc 'Upload the mongrel_cluster.yml in release path'
task :upload_mongrel_cluster do
mongrel_conf = {'environment' => 'production',
'port' => 44000,
'pid_file' => "#{shared_path}/pids/mongrel.pid",
'servers' => 4,
'log_file' => "#{shared_path}/log/mongrel.log"}
put mongrel_conf.to_yaml, "#{current_path}/config/mongrel_cluster.yml"
end
desc 'Start mongrel_rails'
task :start do
run "cd #{current_path} && mongrel_rails cluster::start"
end
desc 'Stop mongrel_rails'
task :stop do
run "cd #{current_path} && mongrel_rails cluster::stop"
end
desc 'Restart mongrel_rails'
task :restart do
run "cd #{current_path} && mongrel_rails cluster::stop && mongrel_rails cluster::start"
end
end
Une tâche qui permet d'envoyer mon fichier mongrel_cluster.yml sur le serveur. Une tâche qui démarre le serveur avec mongrel_cluster, une tâche qui arrête le serveur et une tâche qui le redémarre. La tâche d'envoi est bien sûr après la tâche de symlink. Par contre, pour les trois autres tâches, elle remplace en fait les originales qui lancaient FastCGI.
Enfin il ne reste plus que la conf de nginx
upstream mongrel_blog_dev {
server 127.0.0.1:44000;
server 127.0.0.1:44001;
server 127.0.0.1:44002;
server 127.0.0.1:44003;
}
server {
listen 80;
server_name blog.shingara.fr;
location /log_typo {
alias /var/rails/typoblog-dev/log/;
autoindex on;
}
location / {
root /var/rails/typoblog-dev/current/public;
# needed to forward user's IP address to rails
proxy_set_header X-Real-IP $remote_addr;
# needed for HTTPS
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect false;
proxy_max_temp_file_size 0;
#redirect blog to Feedburner
if ($http_user_agent !~ FeedBurner) {
rewrite ^/xml/rss20/feed.xml$ http://feeds.feedburner.com/ProgDreamShiny;
rewrite ^/xml/rss20/comments/feed.xml$ http://feeds.feedburner.com/ProgDreamShinyComments;
}
# If the file exists as a static file serve it directly without
# running all the other rewite tests on it
if (-f $request_filename) {
break;
}
if (!-f $request_filename){
proxy_pass http://mongrel_blog_dev;
}
}
}
[...]
Un nouveau Logger dans Rails Edge
Depuis 2 jours le logger de RubyOnRails dans la version Edge a changé à partir de la révision r7626. En effet avant il y avait une classe logger qui a été remplacé par un BufferLogger.
Ce nouveau Logger est inspiré des travaux de Ezra Zygmuntowicz, qui a réalisé le framework web merb. Ce nouveau logger devrait améliorer les performances de log.
Je trouve que c'est une très bonne chose que la CoreTeam de Rails regarde aussi un peu à coté vers les nombreux framework Web en Ruby pour en prendre le meilleur.
[...]