Archive for Web Dev
09/09/09 15:52 · Publié dans Configuration, Web Dev
Arrg, il faut lire les pages de manuel en entier … iconv et toutes les wrapper dérivés sont influencé par les variables d’environnement LANG, LC_ALL, LC_CTYPE, LC_MESSAGES.
Par exemple :
$ echo éà | LANG=fr_FR.UTF-8 iconv -f UTF-8 -t ascii//translit
ea
$ echo éà | LANG=C iconv -f UTF-8 -t ascii//translit
??
Et comme bien sûr iconv est très bien documenté, il va sans dire que ça été facile de trouver cette bizzarie.
Donc comme on dit dans ces cas là, ce n’est pas un bug mais une fonctionnalité, à voir chez debian :
”Libc6: //translit fails with cyrillic and others”
Et bien sûr quand vous lancez votre application rails avec Webrick dans votre environnement où LANG=fr_FR.UTF-8
$ script/server
Et d’un autre via passenger et que LANG est initialisé à “C”, alors on perd son temps à chercher le problème dans rails ou passenger.
RTFM !
J’aurais bien aimé utiliser iconv avec la locale fr_FR, mais comme j’utilise iconv pour mes permaliens qui ont été généré avec sans locale (LANG=C), alors pour éviter les problèmes, je force l’appli à utiliser LANG=C dans mon config/envirronment.rb
...
ENV['LANG'] = 'C'
...
jusqu’au prochain problème …
Commentaires
26/08/09 12:38 · Publié dans rails, Web Dev
La solution dans l’article précédent ne me plaisait pas, alors j’ai fais ma solution … bon j’avoue j’ai pas cherché s’il existe déjà une solution prête à l’emploi.
Personnellement, je préfère que config. reload_plugins soit à false. Mais je ne veux pas mettre dans mes plugins un bout de code qui dépend plus de l’application et du contexte (development/production) que du plugin lui même.
Je pourrais mettre reload_plugin à true, oui mais je n’ai pas forcément envie de recharger toute la masse de plugin à chaque requête.
Dans un premier temps, on va ajouter une directive de configuration à savoir reloadable_plugins, et on va la traiter au moment du chargement des plugins. Voici le code :
Rails::Configuration.class_eval do
attr_accessor :reloadable_plugins
def initialize_with_reloadable_plugins
initialize_without_reloadable_plugins
self.reloadable_plugins = default_reloadable_plugins
end
def default_reloadable_plugins
[]
end
alias_method_chain :initialize, :reloadable_plugins
end
Rails::Plugin::Loader.class_eval do
def add_plugin_load_paths_with_reloadable_plugins
load_path = add_plugin_load_paths_without_reloadable_plugins
plugins.each do |plugin|
if configuration.reloadable_plugins.include?(plugin.name.to_sym)
ActiveSupport::Dependencies.load_once_paths -= plugin.load_paths
end
end
load_path
end
alias_method_chain :add_plugin_load_paths, :reloadable_plugins
end
qu’on va mettre dans lib/configuration_reloadable_plugins.rb par exemple.
Ensuite ajouter dans le fichier config/environnement.rb, juste après le boot.rb (l’ordre est important)
...
require File.join(File.dirname(__FILE__), 'boot')
require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')
require 'lib/configuration_reloadable_plugins'
...
Et toujours dans config/environnement.rb on indique les plugins à recharger :
...
Rails::Initializer.run do |config|
config.reloadable_plugins = [ :foo, :bar ]
config.reload_plugins = false
...
end
...
Et pour vérifier que c’est bon :
$ script/console
>> ActiveSupport::Dependencies.load_once_paths.select{ |p| p =~ /foo/ }
=> []
Commentaires
25/08/09 20:24 · Publié dans rails, Web Dev
Les problèmes avec rails 2.3 continuent.
J’utilise depuis longtemps le plugin rails-engines qui permet de transformer une application en un plugin.
Et nouveauté de la version 2.3 de rails, RailsEngine y a été incorporé. Mais comme certains plugins qui ont été incorporé (has_finder, globalize, …) à chaque fois ce n’est pas complètement, bref il faut quand compléter les fonctionnalités en installant le plugin engine expurgé du code commun avec rails.
Mais bon ça bug encore, on obtient un :
A copy of X has been removed from the module tree but is still active!
ou bien un
can’t dup NilClass
uniquement en mode dev … grrr
Alors heureusement, d’autres sont passé par là et certains ont déjà résolu le problème en ajoutant un unloadable dans la classe concernée
class Toto
unloadable
end
That’s it !
UPDATE :
En lisant les commentaires en fait ce n’est pas la bonne solution. En fait il faut lire la doc, enfin la doc dans le code :) dans railties/lib/initializer.rb :
# Enables or disables plugin reloading. You can get around this setting per plugin.
# If reload_plugins? is false, add this to your plugin's init.rb
# to make it reloadable:
#
# ActiveSupport::Dependencies.load_once_paths.delete lib_path
#
# If reload_plugins? is true, add this to your plugin's init.rb
# to only load it once:
#
# ActiveSupport::Dependencies.load_once_paths << lib_path
#
C’est clair ! soit d’office vous ne voulez pas du tout recharger les plugins (reload_plugin à false), et seulement certains (ceux que vous développez par exemple) alors il faut mettre dans le init.rb :
# config/environments/development.rb
config.reload_plugins = false
# plugin's init.rb : remove plugin from unloadable list
ActiveSupport::Dependencies.load_once_paths -= load_paths
soit l’inverse vous voulez que tous les modules soient rechargeable (reload_plugins à true), sauf certains :
# config/environments/development.rb
config.reload_plugins = true
# plugin's init.rb : add plugin in unloadable list
ActiveSupport::Dependencies.load_once_paths += load_paths
UPDATE 2
ou alors encore mieux voir l’article sur l’extension pour rails
Commentaires (1)
25/08/09 20:11 · Publié dans rails, Web Dev
Ah les joies de se mettre à jour et son code à l’occasion … Oui depuis longtemps je trainais avec rails 1.2.6 (oui je sais ça commence à dater mais j’ai mes raisons). Il me tardait donc de pouvoir utiliser les nouvelles versions de rails avec son lots d’améliorations.
Bon tout d’abord grosse surprise un bug uniquement présent en development, et pour cause il concerne le système de déchargement/rechargement du code de l’application.
ça donne soit un
stack level too deep
ou alors un pénible
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:142:in `create_time_zone_conversion_attribute?'
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:75:in `define_attribute_methods'
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:71:in `each'
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:71:in `define_attribute_methods'
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:242:in `method_missing'
Le problème semble être valable depuis rails 2.2 et toujours pas corrigé. Il semble que ce ne soit pas une priorité car le problème se pose uniquement en mode development.
Donc la solution est de patcher rails en attendant. Patch qui se trouve dans le ticket chez lighthouseapp :
if ENV['RAILS_ENV'] != 'production'
class ActiveRecord::Base
class_eval do
def self.reset_subclasses
nonreloadables = []
subclasses.each do |klass|
unless ActiveSupport::Dependencies.autoloaded? klass
nonreloadables << klass
next
end
klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) }
klass.instance_methods(false).each { |m| klass.send(:undef_method, m) unless m =~ /^id(=$|\?$|$)/ }
end
@@subclasses = {}
nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass }
end
end
end
end
Voilà et maintenant ça roule on peut développer en paix.
Commentaires
20/08/09 10:01 · Publié dans rails, Web Dev
Dans rails, on trouve des pépites et with_scope en est une. Une vieille pépite et toujours pas finie, je serais tenté de dire.
Par exemple, il ne tient pas compte de la clause :order.
De mon côté, j’ai besoin d’un ordre précis pour faire le merge de mes jointures.
Prenons l’exemple suivant :
class Dumb
class << self
def foo_bar
with_scope(:find => { :join => "INNER JOIN bar ON bar.id=foo.bar_id"}) do
want_foo
end
end
def want_foo
with_scope(:find => { :join => "INNER JOIN foo ON foo.id=dump.foo_id"}) do
# do your stuff
...
end
end
end
end
... INNER JOIN bar ON bar.id=foo.bar_id INNER JOIN foo ON foo.id=dump.foo_id ...
... ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'foo.bar_id' ..
On souhaite avoir l’ordre inversé genre :
... INNER JOIN foo ON foo.id=dump.foo_id INNER JOIN bar ON bar.id=foo.bar_id ...
Voici la solution :
...
do_reverse_merge_joins do
def foo_bar
with_scope(:find => { :join => "INNER JOIN bar ON bar.id=foo.bar_id"}) do
want_foo
end
end
end
...
et le patch ou l’extension comme vous voulez (testé pour rails 2.3)
ActiveRecord::Base.class_eval do
class << self
def merge_joins_with_reverse(*joins)
merge_joins_without_reverse(reverse_merge_joins? ? joins.reverse : joins)
end
alias_method_chain :merge_joins, :reverse
def do_reverse_merge_joins(&block)
set_reverse_merge_joins
result = yield
reset_reverse_merge_joins
result
end
def reset_reverse_merge_joins
set_reverse_merge_joins(nil)
end
def set_reverse_merge_joins(value = true)
Thread.current[:"#{self}_reverse_merge_joins"] = value
end
def reverse_merge_joins?
Thread.current[:"#{self}_reverse_merge_joins"]
end
end
end
Commentaires
01/07/08 22:32 · Publié dans Web Dev
Une chose à laquelle je pense depuis quelque temps pour mes dev javascript : qu’un acteur majeur du dev et plus particulièrement du dev web prenne l’initiative d’héberger les principales librairies Javascript Protoype, Jquery, Mootools, … Je l’attendais de la part de Yahoo, c’est venu de Google.
Ces librairies sont maintenant énormément utilisées pour animer les pages web, avec plein de widget réalisés à droite à gauche, et donc on retrouve dans le cache des navigateurs plusieurs la même version de la même librairie. Dommage. Perte de place et de bande passante (ok très minime), et surtout perte de temps (téléchargement).
Ensuite l’étape suivante serait la normalisation des ces interfaces de programmation, pour disposer d’appels communs (et surtout ne pas avoir 5 versions du même widget genre lightbox) et de les intégrer soit comme plugin, soit comme dans le coeur du moteur javascript … enfin je doute qu’ on en arrive là … cependant quand j’entends Mozilla annoncer qu’ils vont porter leur attention sur leur moteur javascript …
Et pour les plus curieux un petit tuto … pour l’utilisation avec RubyOnRails of course
Commentaires fermés