Archive pour geek
Par Meuble le Mercredi 27 octobre 2010 à 11h11 · Catégorie : geek
· Mots clés : bash, ruby, rvm
Now that Rails 3 is out, I'm starting to use it on recent application. But I also have some work to do on older applications from time to time.
The first annoying thing is that older applictions are built for Ruby 1.8.6
and Rails 3
works with Ruby 1.9.2
. The other thing is that the rails command is radicaly different from Rails 2.3.8
to Rails 3
.
Using RVM, I'm able to easily switch from one Ruby version to another and from one gems configuration to another. And this depending on the shell I am on.
The counterpart of this is that I'm very confused and never know on which configuration my shell is currently. So I needed a clear way to know it. It would be great if the prompt can tell it to me. Here is how to do that with bash :
# Copy this in ~/.bashrc
__ruby_ps1 ()
{
local g=`ruby -v | cut -d' ' -f2`
if [ -n "$1" ]; then
printf "$1" "${g}"
else
printf "(%s)" "${g}"
fi
}
export PS1='\u@\h$(__ruby_ps1):\w\$ '
Commentaires Fermés (2)
Par Meuble le Samedi 09 octobre 2010 à 00h12 · Catégorie : geek
· Mots clés : osdc, schedule
Samedi 9 et dimanche 10 octobre 2010 (dans 8h, en gros) si tiendrons la 2eme édition de l'OSDC.fr à la Villette.
Afin de bien préparer mon week end, et en volant une idée originale de Sunny, j'ai identifié les présentation que je voulais suivre à grand renfort de monospace.
1 caractère == 5 minutes
[A] : Agora
[N] : Classe Numérique
* : durée de la présentation
- : je serais à la présentation du dessus
Samedi matin :
10h00 [A] Discour
**10H10
10h10 [A] Presentation sponsors
*****10h35
10h40 [A] Nouveautés de la version 9 de PostgreSQL
********11h20
--------
10h40 [N] Listen and look at your PHP code
********11h20
11h25 [A] Introduction à Riak
****11h45
11h25 [N] COMET, l'autre direction du web
****11h45
----
11h50 [A] Présentation de Gephi, logiciel de visualisation de graphes
********12h30
--------
11h50 [N] Présentation de Symfony2
********12h30
Samedi après midi :
14h [A] Organisation du projet PostgreSQL
********14h40
--------
14h [N] Services web SOAP et REST avec symfony
********14h40
14h45 [A] Wrangling Git: Advanced Tips and Tricks
********15h25
--------
14h45 [N] Plone 4, le CMS haut de gamme
****15h05
15h05 [A] Comment déployer des démos Drupal, Plone ou OpenERP en 1 clic
****15h25
15h30 [N] Git::Repository: contrôler Git depuis Perl
********16h10
15h30 [N] Choisir un outil CMS
********16h10
--------
16h30 [A] ooc
********17h10
--------
16h30 [N] Plack
********17h10
17h15 [A] NodeJS
********17h55
--------
17h15 [N] Le développement web avec Perl Dancer
********17h55
Dimanche matin :
10h00 [A] Accueil
**10h10
--
10h10 [A] Présentation du langage Clojure
****10h30
----
10H10 [N] Can we beat Perl hash table
****10h30
10h35 [A] Hard-core bug reporting
****10h55
10h35 [N] Spore, une spécification pour des clients ReST
****10h55
----
11h05 [A] Tracing and profiling production code with SystemTap
********11h45
11h05[N] Redis
********11H45
--------
11H50 [A] Chef: cuisiner ses infrastructures
********12h30
11h50 [N] Introduction à Smalltalk
********12h30
--------
Dimanche après midi :
14h [A] Langage de programmation Go
********14h40
--------
14h [N] Web Development with Seaside
********14h40
14h45 [A] Perl 6: there's some madness to the method after all
********15H25
--------
14h45 [N] Développement dynamique avec Pharo
********15h25
15h30 [A] Perl 6 Signatures: The Full Story
********16h10
15h30 [N] Programmer des robots et des systèmes embarqués avec Smalltalk
********16h10
--------
16h25 [A] Taking Rakudo Forwards: What I'm Hacking On
********17h05
16h25[N] L'animation web en demo
********17h05
--------
17h10 [A] Présentations éclairs
********17h50
--------
17h50 [N] Discours de clôture
**18h00
--
Commentaires Fermés
Par Meuble le Mercredi 10 février 2010 à 23h11 · Catégorie : geek
· Mots clés : actionscript, code, flash, mtasc, sound
I wanted to write a post on an open source old initiative to build Flash application without any Adobe stuff : mtasc. This is for later.
For a professionnal project, I had to make a mp3 streaming player for some famous french radios. And remember I hate Flash.
I was tempted to try it with Javascript, you know, with something like :
<script>
function EvalSound(soundobj) {
var thissound=document.getElementById(soundobj);
thissound.Play();
}
</script>
And then :
<embed src="success.wav" autostart=false width=0 height=0 id="sound1" enablejavascript="true" />
<form>
<input type="button" value="Play Sound" onClick="EvalSound('sound1')">
</form>
But even if I wasn't sure that stremed mp3 (you know, endless files) were compatible with this, some Facebook specific required features prevent me to go further. I had to use Flash.
Since I don't have any licence for using Flash IDE, I've found mtasc. And started to code the player with actionscript 2. The code to load and play a sound is pretty simple :
public class SoundPlayer {
private var _sound:Sound;
private var _soundUrl:String;
public var isPlaying:Boolean = false;
public var isLoaded:Boolean = false;
public function SoundPlayer(soundUrl) {
_soundUrl = soundUrl;
}
public function preLoadSound():Void {
this._sound = new Sound();
this._sound.loadSound(_soundUrl, true);
}
public function play():Void {
if (!this.isLoaded) {
this.preLoadSound();
}
if (!this.isPlaying) {
this._sound.start(0, 1);
}
this.isPlaying = true;
}
public function stop():Void {
this._sound.stop();
this.isPlaying = false;
this.isLoaded = false;
}
}
And this was good. We went to test it on various computer configurations and it apear that some plugins on Internet Explorer 7 and 8 where causing the browser to freeze and relaunch. We identified this list of plugins, but I'm sure there is some others:
- WsftpBrowserHelper Class
- RealPLayer Downloader and record
- AcrolEHlprObj Class
At first, I thought it was mtasc that didn't compile properly the Sound object, but I tried to compile it with the Flash IDE under the latest Flash versions (> 10) and that didn't resolve the bug.
The answer was to translate the code from ActionScript 2 to ActionScript 3. ActionScript 3 add a new Sound class and Event listener to control it. The code in ActionScript 3 is something like:
package streamPlayer {
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.media.SoundLoaderContext;
import flash.net.URLRequest;
public class SoundPlayer {
private var _sound:Sound;
private var _channel:SoundChannel;
private var _soundUrl:String;
public var isPlaying:Boolean = false;
public var isLoaded:Boolean = false;
public function SoundPlayer(soundUrl) {
_soundUrl = soundUrl;
}
public function preLoadSound() {
this._sound = new Sound();
var req:URLRequest = new URLRequest(_soundUrl);
var context:SoundLoaderContext = new SoundLoaderContext(100, true);
this._sound.load(req, context);
}
public function play() {
if (!this.isLoaded) {
this.preLoadSound();
}
if (!this.isPlaying) {
this._channel = this._sound.play();
}
this.isPlaying = true;
}
public function stop() {
var transform:SoundTransform = this._channel.soundTransform;
transform.volume = 0;
this._channel.soundTransform = transform;
this._sound.close();
this.isPlaying = false;
this.isLoaded = false;
}
}
}
And it work perfectly well!
Commentaires Fermés (4)
Par Meuble le Jeudi 04 février 2010 à 23h11 · Catégorie : geek
· Mots clés : date, rails, ruby, time, timezone
Timezones, along with charset and multi-browser support, are a pain in the ass to deal with.
With rails, since 2.1, timezones are supported by default via the config.time_zone
option :
# config/environment.rb
config.time_zone = ‘UTC’
You can configure it to something else like :
# config/environment.rb
config.time_zone = 'Paris'
Or in the controller, per user basis :
# controllers/application.rb
before_filter :set_time_zone
def set_time_zone
Time.zone = @current_user.time_zone if @current_user
end
With all this, rails and active record handle timezones for you. But be very careful when building SQL queries by hand.
ActiveRecord converts dates to UTC timezone before saving them to the database, and convert them back to the current timezone when you load the record from the database. And this can lead to something strange when doing queries like:
User.all(:conditions => ["created_at > ?", Date.today.at_beginning_of_day])
ActiveRecord converts date, but only when saving or loading records. But you can deal with it if you don't forget timezones:
User.all(:conditions => ["created_at > ?", Time.zone.now.at_beginning_of_day])
Something strange is that Rails adds timezone support to the Time class, but not to the date calculations:
>> Time.zone = 'Paris'
>> Date.today.to_s(:db)
=> "2010-02-05"
>> Time.now.to_s(:db)
=> "2010-02-05 00:07:49" # The same date everywhere
>> Time.zone.today.to_s(:db)
=> "2010-02-05"
>> Time.zone.now
=> Fri, 05 Feb 2010 00:06:13 CET +01:00 # All is right here
Let's make some calculations :
>> Time.zone.today.at_beginning_of_day.to_s(:db)
=> "2010-02-05 00:00:00" # Seems to be ok, but
>> Time.zone.now.at_beginning_of_day.to_s(:db)
=> "2010-02-04 23:00:00" # Woot ! the database is still yesterday !
Something you can do if you absolutely need to use Time.today (something stolen from Barry Hess):
class ::Date
def beginning_of_day_in_zone
Time.zone.parse(self.to_s)
end
alias_method :at_beginning_of_day_in_zone, :beginning_of_day_in_zone
alias_method :midnight_in_zone, :beginning_of_day_in_zone
alias_method :at_midnight_in_zone, :beginning_of_day_in_zone
def end_of_day_in_zone
Time.zone.parse((self+1).to_s) – 1
end
end
Commentaires Fermés
Par Meuble le Vendredi 11 décembre 2009 à 10h10 · Catégorie : geek, Partage
· Mots clés : facebook, presentation, sociabliz, yaps
Yesterday, tuesday december 10th, took place at LeWeb09 a Facebook Developer Garage.
It's an event where local Facebook Application and Facebook Connect developers join together and share on their works. This year, a team of Facebook representatives came from the US to meet local developers and answer specific questions. As a social marketing agency, Sociabliz was naturaly there to share its experience of Facebook development.
I gave a talk on YAPS and other tools i've build to encourage Javascript based UI over Flash based UI in Facebook Application. You can find here the slides of Deep into FBJS. All the event was also live on UStream so you can watch it at this url : http://www.ustream.tv/recorded/2843545 (talks start around 0:50, mine is between 1:19 and 1:35).
The live demo can be found on the yaps demo application
I hate watching me again, I feel so stupid. My english seems so bad, I'm kind of ashamed. Speaking english in front of a hundred people was much harder than I expected. Finding the good words is sometimes painful. Anyway, the talk was good, everybody understood it or at least the slides where helpful.
Commentaires Fermés (1)
Par Meuble le Lundi 30 novembre 2009 à 23h11 · Catégorie : geek, Partage
· Mots clés : berlin, geek, infos, présentation, ruby, sociabliz
Nan, y a pas de rapport. J'suis en retard, c'est tout.
Berlin
Le week end avant-dernier (20-23 novembre), Charlotte et moi sommes parti passer 4 jours à Berlin.
En un mot : unwahrscheinlich !
Bon, pour faire vite, façon carte postale, nous avons décollé de Paris à 6h30, pour atterrir à Berlin vers 8h. Ensuite, train vers le centre ville, visite de l'hôtel et dépôt des bagages, petit dèjeuner à Hackesher Markt, traversée de l'île des Musée, descente de Unter den Linden jusqu'à la porte de Brandebourg, visite du Bundestag et de sa coupole, admiration de la Hauptbahnhof, petite bière au café de la Hamburger Bahnhof et visite de celui ci (musée d'art contemporain). Pour le soir nous avons rejoins Manu accompagné de kiddik et de Johnathan (venus de Copenhague) pour aller manger des raviolis russes dans un resto bulgare, puis pour aller boire un coup non pas au huit millimètre, mais dans un autre bar, typé ancienne Allemagne de l'est.
Le lendemain, levé assez tard pour aller manger des currywurst, voir Checkpoint Charlie, sortir en courant du musée du même nom, vagabonder du coté d'un morceau de mur puis entre les tours de Potsdamer Platz, admirer le chapiteaux du Sony Center et les pub géante d'Intel et Microsoft, et enfin aller boir une bière avec le même Manu dans un bar pas pour touristes dans les tréfonds de Rosenthaler Strasse. Ensuite après une tentative raté de resto, nous avons mangé italien sur la même rue et bu dans un bar à la serveuse sympathique.
Le dimanche, levé plus tôt, nous avons entrepris une journée musées, avec l'ancienne galerie nationnalle, la nouvelle galerie nationnalle et la pinacothèque. Nous avons loupé de peu Bill Kaulitz pour la première d'Arthur und die Minimoys, pour aller manger dans un White Trash Fast Food à la carte hilarante et boire des tequila sunrise et des gin tonic dans le même bar que la veille.
Enfin, le dernier jour, après une visite d'un squatte artistique sur Orianenburger Strasse, nous sommes allés jusqu'à Bellevue et traversé le Tiergarten (en passant par la colonne de la victoire) pour rejoindre Potsdamer Platz. Enfin il a fallu prendre le train pour l'aéroport, non sans encombres du à des travaux et des changements de ligne en teuton. L'atterrissage à Orly fut un peu mouvementé pour cause de météo défavorable et le pilote s'y est pris à deux fois pour poser l'appareil sans dégât.
Pour les photos, c'est sur facebook, avec les commentaires, ou sur imeuble, sans rien.
Blockcamp
Rien à voir, puisqu'il s'agit ici d'un série de mini conférences portant sur Ruby et sur Smaltalk.
Samedi dernier (28 novembre), cet événement a réuni à l'Insia des gens de ces deux mondes. J'y ai rencontré oz, Jean, Renaud, Ol, Damien et d'autres habitués comme Jean Francois (merci à lui pour l'organisation) et Shingara.
J'y ai parlé de ruby et de temps réel. L'effet démo de ce sujet que je ne maîtrisais pas n'a pas manqué : impossible de connecter un vidéo projecteur et la carte Arduino ne répondait pas aux signaux d'upload... Malgré cela, les discussions qui s'en sont suivis ont été très intéressantes. Pour ceux qui veulent, les slides sont là.
Dans la journée, j'ai pu assister à une démo de l'étrange Seaside et de ses copains Magrite et Pier, ainsi qu'à eux présentation d'Ol sur MacRuby et Chef. Je regrette un peu de ne pas m'être plus intéressé au Smalltalk.
Il est à noter que c'était le premier événement que Sociabliz sponsorisait. J'espère que ce ne sera pas le dernier.
Un ami venu du Luxembourg a assisté à une partie des conférences et nous nous sommes rejoint ensuite pour aller manger grec à Cluny et écouter les Bec Bien zen à la péniche Bateau El-Alamein.
Commentaires Fermés
Par Meuble le Lundi 02 novembre 2009 à 23h11 · Catégorie : geek, Partage
· Mots clés : ajax, custom, facebook, fbml, renderer, will_paginate
will_paginate is one of the most used rails plugin. It take care of pagination of a large collectoon of item, automatically limiting records to display. It also display a pagination bar, with next, previous and numbered pages.
The fact is that by default, links are just normal link to relative path. It what you want most of the time. Some times you want some AJAX. There is many different way to do it. But some times, you want some AJAX in a Facebook Application...
Here is how I do it.
# In RAILS_ROOT/app/helpers/remote_link_renderer.rb
class RemoteLinkRenderer < WillPaginate::LinkRenderer
def prepare(collection, options, template)
@remote = options.delete(:remote) || {}
super
@options[:params].is_a?(Hash) ? @options[:params].merge({:only_path => false, :canvas => false}) : @options[:params] = {:only_path => false, :canvas => false}
end
protected
def page_link(page, text, attributes = {})
@template.link_to(text, "#", :onclick => "#{@remote[:method_name]}({url: '#{url_for(page)}', container: '#{@remote[:container]}', parameters: { type: '#{@remote[:type]}' }}); return false;")
end
end
will_paginate allow us to use different renderer in order to customize our pagination. I've build one here. The prepare
method is called by will_paginate to let us initialize our renderer before rendering anything. The main thing is to prepare url_for
to return absolute, non canvas url because the Facebook FBJS AJAX proxy doesn't allow anything else.
In the page_link
method, we generate links displayed by will_paginate. We can't set the href attribute to the url because again, the Facebook FBJS AJAX proxy doesn't allow anything but #
here. And since in Profile Boxes and Tabs, we can't use onLoad event, we use onClick in order to call our AJAX builder. Parameters of that function are specific to my need, but it's just to show you that we can pass in variables and build a custom link.
Here is a sample code showing the way to specify our renderer to will_paginate.
# Somewhere in the view
<%= will_paginate users, :renderer => 'RemoteLinkRenderer' , :remote => {:method_name => 'ajaxizer', :container => container, :type => type}, :previous_label => "precedent", :next_label => "suivant" %>
Commentaires Fermés
Par Meuble le Jeudi 02 juillet 2009 à 02h02 · Catégorie : geek, Partage
· Mots clés : code, facebook, javascript, yaps
I've maid this twit saying that I built a JavaScript image preloader. Since many wanted to see it. There it is.
I wanted to preload image for a Facebook application displaying a JavaScript photo viewer widget. And when developing Facebook applications, you have deal with Facebook JavaScript rules and what they call FBJS. I already built a FBJS framework, YAPS, helping me (and other developpers) to do simple javascript tasks.
But YAPS can't replace the Image JavasScript class nor the document.images that Facebook prevent us tu use. So I built this code to preload images in a Facebook environment.
Code :
// An image preloader without using Image class nor document.images
// Built for a Facebook environment where those two are forbiden. May not work in a regular web page.
// Just change
function Preloader(options) {
var defaultSettings = {
preloaderID: "preloader_id",
container: document.body
};
this.settings = this.extend(defaultSettings, options || {});
this.buildPreloader();
};
Preloader.prototype = {
extend: function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
},
// Prepare the preloader. Just a IMG html element hidden with css.
buildPreloader: function(preloaderId) {
var image = document.createElement('IMG')
.setId(this.settings.preloaderId)
.setStyle({display: 'none'});
this.settings.container.appendChild(image);
},
// Update de src attribute of our hidden tag with the passing url.
// Having the src updated will make the tag to load the image.
preloadPic: function(imageUrl) {
var preloader = document.getElementById(this.settings.preloaderId);
if (preloader) {
preloader.setSrc(imageUrl);
// Don't know why, setting the src make the picture visible.
// Have to hide it again.
preloader.setStyle({display: 'none'});
}
}
};
Usage :
preloader = new Preloader({
preloaderID: "my_image_preloader",
container: document.getElementById("my_container")
});
preloader.preloadPic("http://imeuble.info/assets/2008/5/21/stéphane-akkaoui-maxime-guilbot-discussion_1.jpg");
Improvements :
- If I use the same Preloader instance multiple time in a row, I'm not sure the previous image is entirely preloaded before with change the src attribut with the new url.
- It would have been great if I could passe an Array of urls to the preloader and let him do the work.
- It must be many other possible improvments. This feat my needs for the moment. Please feel free to modify it. Post an updated code in the comments.
Commentaires Fermés (2)
Par Meuble le Mercredi 10 juin 2009 à 09h09 · Catégorie : Delirious, geek
· Mots clés : code, github, ruby, squarespace, twitter
- Find a contest : http://www.squarespace.com/iphone
- Read the official rules.
- Find out that you can do watever you want to win (No RulZ !!)
- Build a tiny ruby script : http://github.com/meuble/SquareSpace-hack/tree/master
- Register as a new twitter account (or not, you can do it with your own personal account) : http://twitter.com/fake_meuble
- Launch the script
- Spam, spam and spam again
- Wait
- And win ! (maybe)
Commentaires Fermés (5)
Par Meuble le Mardi 21 avril 2009 à 21h09 · Catégorie : geek, Partage
· Mots clés : "best practices", ruby
Je suis loin d'être un maître de la programmation. Je suis sûr que mon code comporte lui aussi des trucs un peu moche. Mais quand même, des fois faut pas pousser.
Il y a des trucs qu'il ne faut pas faire.
Et il y a des gens pour les faire...
Redirection après login
if session[:return_to]
redirect_to root_path
else
redirect_to user_profile_url(@user_session.account.user)
end
Ca par exemple ça ne sert à rien. Pourquoi se préoccuper d'où vient l'utilisateur, pourquoi s'embêter à stocker ses volontés quand il se confronte à un accès restreint, si on n'en tiens pas compte ? Et si l'utilisateur ne voulait pas aller à l'accueil ?
Des boutons radio à valeurs variables
<label><%= t('title') %></label>
<span class="radio">
<%= m.radio_button :title, t('mister') %>
<%= m.label :title_mister, t('mister') %>
<%= m.radio_button :title, t('madam') %>
<%= m.label :title_madam, t('madam') %>
<%= m.radio_button :title, t('miss') %>
<%= m.label :title_miss, t('miss') %>
</span>
Vouloir internationaliser une application, c'est une bonne chose. Mais il y a des excès à ne pas atteindre. Si la valeur d'un bouton radio est internationalisé, la valeur sera différente en fonction de la langue de l'utilisateur. Déjà, seul comme ça ça peut être confusant.
Mais si en plus on enregistre le sex de l'utilisateur sans plus de contrôle, on aura en base dans le champs title : "Monsieur", "Madame" ou "Mademoiselle" mais aussi "Mister", "Mrs", "Miss", etc...
Imaginez alors qu'on veuille chercher tout les messieurs de notre application ? SELECT * FROM users WHERE title in ("Monsieur", "Mister")
. Et si maintenant je rajoute une langue (au hasard, le russe), faut que je modifie toutes mes requêtes et que je rajoute господи́н
.
Trop de normalisation, sans transaction
Sur une application, on a des membres. Ces membres sont de différents type, peuvent se connecter de différentes manières (classique, facebook connect, openId, ...), possèdent d'autres objets (articles, commentaires, projets) et ont une adresse et une image.
Si on normalise, on a un membre, qui est composé d'un user et d'un compte. Il a aussi une adresse postal (avec vile, code postal et pays) et ses articles. Et pour créer une user ça devient :
def create
@account = Account.new(params[:account])
@member = Member.new(params[:member])
@visual = Visual.new(params[:visual])
@address = Address.new(params[:address])
if @account.valid? & @member.valid? & @visual.valid?
@account.save
@address.save(false)
@member.create_user.account = @account
@member.visual = @visual
@member.address = @address
@member.save
flash[:success] = "Ok."
redirect_to root_path
else
render :action => :new
end
end
C'est long pour un contrôleur, non ? Admettons même que ce se soit dans un modèle, ça reste moche. Tout ces save
dont certains sans validation, peuvent entraîner plein de problèmes :
- Levée d'exception SQL parce qu'il n'y a pas les bons type
- Il n'y a pas de transaction encadrant tout ça. Si ça ne marche pas à un endroit, on se retrouve avec une table bancale, voir corrompue.
- Comme dans l'exemple on pourrait oublier de vérifier certains modèles (ici
@adresse
n'est pas validé et sauvé dans validation).
- La modification d'un tel code n'est pas aisée et devant la confusion, on ne sait pas trop quel serait l'impact d'une modification...
Si au lieu de ça, on démoralisait un peu, on pourrait simplifier les choses. Un utilisateur n'a qu'une adresse postale, donc on peut ajouter les champs rue, ville pays et code postal au membre. De même, il n'a qu'un avatar, et même si d'autres modèle peuvent aussi avoir un avatar, il vaut mieux utiliser le duck typing et les surcharges d'opérateurs que la composition. Enfin, plutôt que de démultiplier les dépendances, on pourrait gérer les types de membre par de l'héritage (spécialisation) plutôt que par de la composition. Cela permet une plus grande généralisation (il y aura une méthode send_message
pour tout le monde, dont le comportement sera différent pour tous).
Commentaires Fermés (6)
Par Meuble le Vendredi 27 mars 2009 à 01h01 · Catégorie : geek, Partage
· Mots clés : code, javascript
Dans bien des langages, il est possible de définir des paramètres optionnels dans la signature des méthodes. Ces paramètres prennent une valeure par défaut s'ils ne sont pas spécifiés à l'appel de la méthode.
Par exemple, on pourrait être tenté d'écrire :
var saySomething = function(value = "default value") {
alert(value);
}
Seulement, en JavaScript, cela ne fonctionne pas.
Par contre, on peu utiliser une propriété de JavaScript pour arriver à nos fins : si un argument est attendu dans la signature mais pas spécifié dans l'appel, il sera alors de tupe "undefined"
. On peut donc faire :
var saySomething = function(value) {
if (typeof value == "undefined") {
value = "default value";
}
alert(value);
}
Seulement, ce n'est pas très élégant. Si nous avons plusieurs arguments optionnel, la succession de structures conditionnelles peut vite devenir ennuyeuse.
Pour y remédier, on peut utiliser les objets. En Javascript, les objets sont des ensembles de clé/valeur dont les premières sont des dénominations et les dernières des instances d'autres objets. Ils sont comparables aux hashes Ruby et on peut avoir des itérateurs dessus grace à l'instruction in et à la structure de bouche for
Du coup, on pourrait imaginer le code suivant :
var extend_instance = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
var saySomething = function(params) {
params = extend_instance({
value: 'default value',
from: 'Anonymous Caword'
}, params);
alert(params.from + "say :" + params.value);
}
L'appel de la méthode change un peu puisqu'il faut maintenant lui donner un objet, mais cela rend le code plus souple aux changement et n'impose aucun ordre aux arguments.
Pour aller encore un peu plus loin et en gardant les avantages de cette méthode, on pourrait se servir de la variable local aux méthodes : arguments
var extend_instance = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
var saySomething = function() {
params = extend_instance({
value: 'default value',
from: 'Anonymous Caword'
},arguments[0] || { });
alert(params.from + "say :" + params.value);
}
Commentaires Fermés (3)
Par Meuble le Mardi 24 mars 2009 à 09h09 · Catégorie : Delirious, geek
· Mots clés : 42, uptime
Wouahou !
[20:53:21][sakkaoui@Sylar](~): uptime
20:53 up 42 days, 42 mins, 7 users, load averages: 0.16 0.28 0.23
C'est bon, je peux l'éteindre et faire toutes les mises à jour. Il a atteint le chiffre parfait, la maturité.
Commentaires Fermés (5)
Par Meuble le Mardi 03 mars 2009 à 11h11 · Catégorie : Delirious, geek
· Mots clés : day, root, square
Nous sommes aujourd'hui le 3 Mars 2009.
Soit le 03/03/09, comme l'écriraient nos amis d'outre-atlantique. Et comme chacun le sait, 3 est la racine carrée de 9.
Ce jour est donc béni des dieux, un jour où tout peut arriver : la fin de la guerre dans le monde, la venue des extraterrestres sur terre, l'abolition des frontières, un noir à la présidence des États Unis d'Amérique (ha, non, ça c'est déjà fait), ...
C'est quand même rare, les jours de racine carrée, non ? Imaginez vous que le précédent était le 2 février 2004. Et que le prochain sera le 4 Avril 2016 ! En fait, quand on compte, il ne peut y en avoir que 9 par siècle, tous pareil.
Petit lien pour en savoir plus : Wikipedia, The Square Root Day.
Commentaires Fermés (4)
Par Meuble le Mercredi 25 février 2009 à 12h12 · Catégorie : geek
· Mots clés : safari
Wouawou ! Apple a sorti une nouvelle version de Safari.
Parmi les nouvelles fonctionnalités, je retiens :
- La barre d'onglet est passée au-dessus de la barre d'URL
- Le signal de chargement est passé d'une barre de progression bleue à un spinner
- La navigation dans l'historique se fait via coverflow
- Une jolie présentation des sites les plus visités en page d'accueil
- Un changement de l'autocomplétion dans la barre d'URL (pour une recherche à la Firefox)
- Un léger redesign de la page des signets
- Un Inspecteur Web bien plus performant et avec plus de fonctionnalité que l'ancien (un firebug-like, maintenant)
Y a un truc que je n'aime pas : la barre d'onglet au dessus de la barre d'URL.
En cherchant dans les préférences, il n'y a rien qui me permette de la redescendre. Alors il a fallu ruser.
Quelles sont les clés que Safari utilise ?
Bah oui, souvent dans les programmes Apple, on peut se détourner les comportements par défaut en jouant avec des clés, un peu comme les registres.
Alors parsons le binaire pour voir ce qu'il a dans le ventre :
sakkaoui@mcMeuble:~$ strings /Applications/Safari.app/Contents/MacOS/Safari | grep Safari4
DebugSafari4TabBarIsOnTop
DebugSafari4IncludeToolbarRedesign
DebugSafari4IncludeFancyURLCompletionList
DebugSafari4IncludeGoogleSuggest
DebugSafari4LoadProgressStyle
DebugSafari4IncludeFlowViewInBookmarksView
DebugSafari4TopSitesZoomToPageAnimationDimsSnapshot
DebugSafari4IncludeTopSites
BookmarksToolbarProxiesWereConvertedForSafari4
Bah voilà ! Ce qu'on cherchait est en premier. On peut jouer avec ces options grâce à la commande defaults, qui nous permet d'ajouter/supprimer/modifier des clés dans les préférences de l'utilisateur.
On écrit avec :
defaults write domain { 'plist' | key 'value' }
On supprime avec :
defaults delete [domain [key]]
Allez, on va faire les options dans l'ordre.
Déplacer la barre de signet
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4TabBarIsOnTop -bool NO
Ce qui aura pour effet de remettre la barre d'onglet au bon endroit : en dessous de la barre d'URL.
Jouer avec le signal de chargement
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4IncludeToolbarRedesign -bool NO
On remplace le spinner de la barre d'URL (placé à droite normalement) par un autre spinner, placé à gauche, en forme de camembert bleu clair se remplissant
defaults write com.apple.Safari DebugSafari4LoadProgressStyle -bool NO
On remet la barre de progression bleue comme avant (on enlève les spinner)
À noter qu'aucune des deux options ne change le spinner sur les onglets qui ne sont pas au premier plan.
Gérer les autocomplétions
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4IncludeFancyURLCompletionList -bool NO
Reviens à l'ancien autocompléteur de la barre d'URL, qui cherche uniquement dans les URL (et non dans les titres de page).
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4IncludeGoogleSuggest -bool NO
Désactive l'autocomplétion de la recherche Google.
Désactiver le coverflow
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4IncludeFlowViewInBookmarksView -bool NO
Enlève le coverflow dans la page des signets.
Jouer avec la nouvelle fonctionnalité des top pages
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4TopSitesZoomToPageAnimationDimsSnapshot -bool NO
Enlève le masque transparent noir au chargement d'une des top page (après avoir cliqué dessus).
sakkaoui@mcMeuble:~$ defaults write com.apple.Safari DebugSafari4IncludeTopSites -bool NO
Désative complètement la fonctionnalité top page.
Commentaires Fermés
Par Meuble le Mercredi 28 janvier 2009 à 09h09 · Catégorie : Delirious, geek
· Mots clés : irc
Day changed to 27 Jan 2009
10:12 < meuble> _o/
10:19 < al> \o_
10:28 < _Nono> _o_
18:11 < negat|f> \o/
18:26 < fuse> \o\
Day changed to 28 Jan 2009
Voilà des geeks accessibles : ils parlent en langue des signes pour se mettre à la place de leurs amis handicapés et concevoir un moyen de communication numérique commun.
Merci à eux.
Commentaires Fermés (1)