IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Ruby on Rails Discussion :

[Debutant] Question sur les |


Sujet :

Ruby on Rails

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 95
    Points : 71
    Points
    71
    Par défaut [Debutant] Question sur les |
    Bonjour,
    Désolé si la question a déjà été posé, mais je comprends pas la logique dans RoR sur les '|'

    Un exemple simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     create_table :utilisateurs do |t|
    comment le traduire ? cette fonction renvoie un objet pointant vers 't' ? et les | sont-elles obligatoires ?

    Je sais c'est peut etre (surement) une question bête, mais j'essaie d'apprendre ce langage avec un livre, et ce n'est pas expliqué et ca me bloque

    Merci d'avance

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Février 2008
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 135
    Points : 94
    Points
    94
    Par défaut
    j'ai un de peu mal aussi avec ca . c'est une specificité de ruby.

    le do |t| est ce qu'on appelle un bloc, un ensemble de traitement que devra exécuter la fontion . les traits verticaux |variable| designe une variable du bloc.

    Certaine fonction comme each ou upto accepte des paramètre de type bloc.

    ex :

    0.upto(10) do |i|
    print i, " "
    end

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 95
    Points : 71
    Points
    71
    Par défaut
    ok, on peut dire que les | vont recevoir la variable retourné par upto() ?

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 657
    Points : 910
    Points
    910
    Par défaut
    En quelques sorte oui, le contenu des pipes déclare les variables utilisées dans le bloc.


    En javascript (et d'autre langages qui acceptent des fonctions anonymes), on peut écrire quelque chose d'équivalent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    create_table('utilisateur', function(t) {
      ... faire qqch avec t ...
    });
    Pour mieux comprendre comment ça marche, il faut que tu comprennes comment un bloc est appelé par la méthode. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    def toto(&block)
      block.call("Hello")
    end
     
    toto do |texte|
      puts "Cette methode dit : #{texte}"
    end
    toto do |x|
      puts "Cette methode dit : #{x}"
    end
    # affiche :
    Cette méthode dit Hello
    Cette méthode dit Hello
     
    def toto2(&block)
      block.call("Hello", "world")
    end
    toto2 do |a, b|
      # a => Hello
      # b => world
    end
    Un autre exemple avec une méthode qui prend un argument et un bloc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def with_file(path, &block)
      f = File.new(path, 'r')
      block.call(f)
      f.close
    end
     
    with_file "toto.txt" do |file|
      ... faire qqch avec le fichier ... (file.read, etc.)
    end
    Cette méthode ouvre un fichier, le passe au bloc puis le referme. En réalité, c'est ce que fait déjà File.new


    Quelques remarques :
    - le bloc et toujours le dernier argument, il est précédé d'un &, il peut avoir n'importe quel nom, mais par convention s'appelle le plus souvent "block"
    - block.call est (à quelques subtils détails près) équivalent au mot clé yield
    - ces deux syntaxes sont aussi équivalentes (la seconde pouvant être écrite sur plusieurs lignes, mais le plus souvent reservée pour les blocs d'une seule ligne) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    methode do |var|
      ...
    end
     
    methode { |var| ... }
    Tu trouveras certainement pas mal de littérature sur le blocs, c'est une fonctionnalité très puissante de Ruby. Il faut certes un peu d'habitude, mais c'est utilisé à tour de bras : tableaux (each, collect, inject...), interations (each, upto, times...), DSL (dont Rails use et abuse ), etc.
    Toute la documentation Ruby on Rails : gotapi.com/rubyrails
    Mes articles :
    > HAML : langage de template pour Ruby on Rails

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 95
    Points : 71
    Points
    71
    Par défaut
    Ok, si j'ai bien compris la fonction exécutera le code qu'elle contient a chaque appelle du paramètre entre les pipes ? ou j'ai rien compris

    Il y a une équivalence en PHP ? ça pourrait m'aider à mieux comprendre ...

  6. #6
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 657
    Points : 910
    Points
    910
    Par défaut
    Dis comme ça, c'est difficile de savoir si tu as bien compris ou pas
    Malheureusement il n'existe pas de concept équivalent en PHP.

    Les blocs sont une syntaxe particulière pour les fonctions d'ordre supérieures, c'est à dire les fonctions qui prennent des fonctions en argument.
    Tu peux te dire qu'on bloc est un "bout de code" que tu passes en argument à la fonction que tu appelles. Cette fonction fait alors ce qu'elle veut avec ton bout de code (typiquement elle l'appelle une ou plusieurs fois en lui passant des arguments qu'elle a crée).


    Si tu as fait du PHP, il existe une fonction array_map qui peut ressembler au map/collect de Ruby :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function carre($n) {
      return $n*$n;
    }
     
    $nombres = array(2, 5, 10);
    $carres = array_map('carre', $nombres); // execute la fonction "carre" pour tout les éléments du tableau
     
    // $carres -> array(4, 25, 100)
    Maintenant, ce code PHP à quelques limitations : en particulier, la fonction "carre" doit être déclarée auparavant.
    En Ruby, la fonction map/collect de la classe Array fait la même chose, en utilisant un bloc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [2, 5, 10].map { |n| n*n } # => [4, 25, 100]
    Ce qui prennait 5 lignes en PHP se fait en une seule ligne de Ruby

    Concernant les variables du bloc, tu vois bien ici que "n" pourrait être remplacé par n'importe quoi : [2, 5, 10].map { |i| i*i } est évidemment strictement identique, tout comme en PHP on aurait pu écrire :
    function carre($i) { return $i * $i; }


    La notion de fonction d'ordre supérieur n'est pas forcément évidente lorsqu'on n'y est pas habitué. Comme toujours, c'est la pratique qui permet de mieux assimiler ces concepts.


    Dans ton exemple original, create_table, tu utilises le DSL des migrations de Rails. Un DSL, c'est en quelque sorte un "mini-framework" dont l'objectif est de rendre une tâche (ici les migrations de base de données) le plus proche possible du langage naturel (anglais).

    Le bloc est ici une manière de dire :
    "create table utilisateurs with strings nom, prenom and integer age"
    Ceci est un code Ruby qui fonctionne tout à fait, très proche de cette phrase :
    create_table(:utilisateurs) { |t| t.string :nom, :prenom; t.integer :age }
    La raison pour laquelle on l'écrit sur plusieurs lignes est évidement que c'est beaucoup plus lisible
    Toute la documentation Ruby on Rails : gotapi.com/rubyrails
    Mes articles :
    > HAML : langage de template pour Ruby on Rails

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 95
    Points : 71
    Points
    71
    Par défaut
    Ok d'accord ça commence a s'éclaircir, pour voir si j'ai bien compris, je reprends un de tes exemples :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    def toto(&block)
      block.call("Hello")
    end
     
    toto do |texte|
      puts "Cette methode dit : #{texte}"
    end
    Lors de l'appelle de la fonction toto, celle ci reçoit donc la ligne avec le puts et comme argument texte ?

    J'ai bon ?

  8. #8
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 652
    Points
    652
    Par défaut
    Les | sont pour définir une variable locale à un bloc.

    En php quand tu écris une fonction, tu utilises des variables locales à la fonction.
    Ces variables ont une portée uniquement dans la fonction. En dehors de la fonction, elles n'existent plus.
    Beh là c'est pareil, mais c'est encore plus restrictif. Les variables encadrées par des | sont locales au bloc. Une fois sorti du bloc elle n'existent plus.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 95
    Points : 71
    Points
    71
    Par défaut
    Ok daccord j'ai pratiquement compris

    Mais dans cet exemple, l'objet t est de quel type ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
         create_table :pages do |t|
           t.column :name, :string, :limit => 30
           t.column :content, :text
         end
    Je me pose peut etre trop de questions ...

  10. #10
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 657
    Points : 910
    Points
    910
    Par défaut
    En effet, tu te poses trop de questions

    Ruby est un langage dynamique, et accorde peu d'importance aux types. Tu sais juste que l'objet qui est passé à ton bloc (et que tu met dans "t") répond au message "column" (on dit aussi qu'il possède la méthode "column").

    Si tu veux vraiment savoir quelle est la classe de "t" tu peux utiliser t.class (ou aller voir le code de create_table) mais tu n'as généralement pas besoin de savoir ça.
    Toute la documentation Ruby on Rails : gotapi.com/rubyrails
    Mes articles :
    > HAML : langage de template pour Ruby on Rails

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 95
    Points : 71
    Points
    71
    Par défaut
    Ha ok parce que je trouvais bizarre d'appliquer sur un objet une methode alors qu'il n'a même pas été instancié

Discussions similaires

  1. debutant : question sur les rapports
    Par kam81 dans le forum Jasper
    Réponses: 2
    Dernier message: 07/11/2008, 11h54
  2. [debutant]Question sur les .ear
    Par smutmutant2003 dans le forum ANT
    Réponses: 4
    Dernier message: 28/02/2008, 09h21
  3. [Debutant]question sur les Idl
    Par smutmutant2003 dans le forum CORBA
    Réponses: 5
    Dernier message: 25/06/2007, 10h27
  4. [debutant]Question sur les Jpanels
    Par mikedavem dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 09/05/2006, 14h38
  5. [debutant] Question sur les données.
    Par Norabfr dans le forum Débuter
    Réponses: 4
    Dernier message: 03/01/2006, 13h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo