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 :

[Débutant] Pb de liaison {MySQL - Scaffold - Relation}


Sujet :

Ruby on Rails

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 114
    Points : 73
    Points
    73
    Par défaut [Débutant] Pb de liaison {MySQL - Scaffold - Relation}
    Bonjour à tous,

    En gros, je souhaiterais commencer un projet très simple pour apprendre RoR. Mais même avec un projet très simple, j'ai déjà un problème. Je pense que le plus efficace est de citer une à une chaque étape et de vous présenter le problème lorsqu'il survient...

    Ma base de données test contient 2 tables. Schématiquement, mes tables sont liées comme ceci :
    users (1,1) -> (0,*) homes
    Afin d'être le plus clair possible, voici le dump de l'ensemble :
    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
    CREATE TABLE `homes` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(32) NOT NULL,
      PRIMARY KEY  (`id`),
      UNIQUE KEY `name` (`name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
     
    INSERT INTO `homes` (`id`, `name`) VALUES (1, 'Blue home');
     
    CREATE TABLE `users` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(32) NOT NULL,
      `home_id` int(11) NOT NULL,
      PRIMARY KEY  (`id`),
      UNIQUE KEY `name` (`name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
     
    INSERT INTO `users` (`id`, `name`, `home_id`) VALUES (1, 'Jo', 1);
    Et voici un apperçu de mes 2 tables à ce stade.

    • homes
      id name
      1 MyHome
    • users
      id name home_id
      1 Jo 1



    Jusque là, tout va bien en fait. Voici ensuite les commandes que j'exécute :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home:~/www/rails cyril$ rails test
    create
    create app/controllers
    create app/helpers
    create app/models
    create app/views/layouts
    create config/environments
    create components
    create db
    create doc
    create lib
    create lib/tasks
    create log
    create public/images
    create public/javascripts
    create public/stylesheets
    create script/performance
    create script/process
    create test/fixtures
    create test/functional
    create test/integration
    create test/mocks/development
    create test/mocks/test
    create test/unit
    create vendor
    create vendor/plugins
    create tmp/sessions
    create tmp/sockets
    create tmp/cache
    create Rakefile
    create README
    create app/controllers/application.rb
    create app/helpers/application_helper.rb
    create test/test_helper.rb
    create config/database.yml
    create config/routes.rb
    create public/.htaccess
    create config/boot.rb
    create config/environment.rb
    create config/environments/production.rb
    create config/environments/development.rb
    create config/environments/test.rb
    create script/about
    create script/breakpointer
    create script/console
    create script/destroy
    create script/generate
    create script/performance/benchmarker
    create script/performance/profiler
    create script/process/reaper
    create script/process/spawner
    create script/runner
    create script/server
    create script/plugin
    create public/dispatch.rb
    create public/dispatch.cgi
    create public/dispatch.fcgi
    create public/404.html
    create public/500.html
    create public/index.html
    create public/favicon.ico
    create public/robots.txt
    create public/images/rails.png
    create public/javascripts/prototype.js
    create public/javascripts/effects.js
    create public/javascripts/dragdrop.js
    create public/javascripts/controls.js
    create public/javascripts/application.js
    create doc/README_FOR_APP
    create log/server.log
    create log/production.log
    create log/development.log
    create log/test.log
    Mon projet est crée. Je l'ouvre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home:~/www/rails cyril$ cd test/
    Maintenant, j'édite le fichier database.yml.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home:~/www/rails/test cyril$ vi config/database.yml
    Ma base de données est maintenant accessible par RoR. De plus, elle est conforme aux conventions de RoR :
    1. les clefs primaires sont nommées id ;
    2. la clef étrangère de la table users se nomme home_id ;
    3. les tables sont au pluriel.

    Je demande donc à RoR de créer deux échaffaudages (un par table) :
    • homes
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      home:~/www/rails/test cyril$ ruby script/generate scaffold home
      exists app/controllers/
      exists app/helpers/
      create app/views/homes
      exists test/functional/
      dependency model
      exists app/models/
      exists test/unit/
      exists test/fixtures/
      create app/models/home.rb
      create test/unit/home_test.rb
      create test/fixtures/homes.yml
      create app/views/homes/_form.rhtml
      create app/views/homes/list.rhtml
      create app/views/homes/show.rhtml
      create app/views/homes/new.rhtml
      create app/views/homes/edit.rhtml
      create app/controllers/homes_controller.rb
      create test/functional/homes_controller_test.rb
      create app/helpers/homes_helper.rb
      create app/views/layouts/homes.rhtml
      create public/stylesheets/scaffold.css
    • users
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      home:~/www/rails/test cyril$ ruby script/generate scaffold user
      exists app/controllers/
      exists app/helpers/
      create app/views/users
      exists test/functional/
      dependency model
      exists app/models/
      exists test/unit/
      exists test/fixtures/
      create app/models/user.rb
      create test/unit/user_test.rb
      create test/fixtures/users.yml
      create app/views/users/_form.rhtml
      create app/views/users/list.rhtml
      create app/views/users/show.rhtml
      create app/views/users/new.rhtml
      create app/views/users/edit.rhtml
      create app/controllers/users_controller.rb
      create test/functional/users_controller_test.rb
      create app/helpers/users_helper.rb
      create app/views/layouts/users.rhtml
      identical public/stylesheets/scaffold.css

    Bizarrement, d'après ce que j'ai pu lire comme information, il semblairait qu'il faille encore préciser, dans chaque modele, la relation affectée. J'ai donc entré pour le modèle Home :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home:~/www/rails/test cyril$ vi app/models/home.rb
    Et j'ai ajouté ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Home < ActiveRecord::Base
      has_many :users
    end
    Puis pour le modèle User :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home:~/www/rails/test cyril$ vi app/models/user.rb
    J'y ai ajouté ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class User < ActiveRecord::Base
      belongs_to :home
    end
    Pour ma part, je trouve ça bizarre car RoR est censé ~comprendre~ tout via des conventions. En gros, RoR n'a besoin que du minimum de configuration possible. Pourtant, il semble nécessaire d'ajouter ces précisions malgré le fait que la structure de la base test l'indique implicitement.
    Bref, c'est le 1er point qui pour moi est louche.
    Ensuite, j'exécute le serveur Web.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home:~/www/rails/test cyril$ ruby script/server
    Et aussitôt, je tape dans Firefox (pour ne pas le citer ) l'adresse : http://127.0.0.1:3000/users/new. Voici une copie de la source du formulaire affiché :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <form action="/users/create" method="post">
    <!--[form:user]-->
    <p><label for="user_name">Name</label><br/>
    <input id="user_name" name="user[name]" size="30" type="text" value="" 
    /></p>
    <!--[eoform:user]-->
    <input name="commit" type="submit" value="Create" />
    </form>
    Et là, je constate une 2ème bizarrerie : il n'y a pas d'entrée home_id.
    Du coup, si je remplie ce formulaire dans mon navigateur (avec par exemple la chaîne "mike" pour le champ name), après la soumission, je m'apperçoie que dans la table users de ma base de données, la valeur du champ home_id de l'occurrence que je viens d'ajouter est égale à 0. Là ça devient plus que louche et la relation ne peut pas fonctionner (car aucune occurrence de la table homes n'a de champ id égal à 0, donc y'aura jamais de liaison entre mes 2 tables).

    Afin d'être aussi clair que possible, voici un 2ème apperçu de mes 2 tables à ce stade.

    • homes
      id name
      1 MyHome
    • users
      id name home_id
      1 Jo 1
      2 Mike 0

    On y voit la dernière ligne où le bug a été mit en rouge.
    Bref, si vous avez une idée pour m'aider à le corriger, ça serait parfait.

    Désolé, c'était un peu long.
    Merci en tout cas pour votre aide

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 25
    Points : 20
    Points
    20
    Par défaut
    Salut tsing et bienvenue dans le monde du développement Rails.

    Je vais tenter de répondre à ton post.

    Premièrement sur ce que tu appelles la "1ere bizarerie". Cela n'en est pas une.

    Comprends bien que Rails, même s'il est basé sur des conventions ne fait pas de "reverse enginering" sur ta table. Ce n'est pas à lui de le faire. Par conséquent, si tu as des clés étrangères dans tes tables, tu dois lui faire comprendre précisément en utilisant comme tu l'as fait "has_many", "belongs_to", etc.

    Là où la convention Rails joue c'est que tu lui dis que y a une clé étrangère mais tu n'as pas besoin de lui dire que la clé étrangère c'est truc_id. Voilà la convention.

    2ème "bizarerie" qui n'en est pas une aussi, il faut simplement comprendre le scaffold dans Rails. Pour moi le scaffold c'est juste un script pour faire joli, pour épater la galerie, les débutants, mais c'est pas un script à forcément utiliser. La plupart des développeurs ne l'utilisent pas. Le script de scaffold ne fait que générer un modèle, un contrôleur et quelques vues génériques autour de ce modèle pour les opérations de bases (CRUD : create update delete). C'est un script générique, qui ne fonctionne que sur un modèle et qui ne gère pas toutes les spécificités, clés étrangères, etc. C'est au développeur après d'adapter le scaffold selon ses besoins.
    Ce que je te conseille c'est en premier de comprendre comment faire les opérations de base sur un modèle simple, sans clé étrangère.
    Puis après de te documenter dans la doc API sur comment gérer les clés étrangères, tu verras que Rails facilite le travail.

    Je te recommande de jouer avec la console pour voir les mécanismes en temps réel. Lance un "./script/console" a partir du dossier de ton appli et teste.

    Dans un autre terminal, fait un "tail -f log/development.log" pour voir en temps réel les requetes envoyées au SGBD.

    Teste voir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    home = Home.new
    home.name = "maison 1"
    user = User.new
    user.name = "utilisateur 1"
    home.users << user
    home.save
    Si tu regarde le log, tu verras les 2 insert avec les bonnes liaisons ! Magique... Et regarde la beauté et la lisibilité du code franchement...

    Tu peux même faire plus court et remplacer les 3 avant dernieres lignes par un create avec passage des attributs du nouvel user en hash.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    home.users.create( { :name => "utilisateur 1" } )
    Une fois que tu auras bien compris comment gérer les associations avec Rails, tu pourras améliorer les formulaires du scaffold générique du modèle User par exemple, en rajoutant une select box qui permettra de choisir le Home à relier au nouvel user... Ce n'est pas Rails et le scaffold qui peut prévoir ce genre de chose...

    J'espère que ma réponse te conviendra et t'encouragera à continuer...

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 114
    Points : 73
    Points
    73
    Par défaut
    Merci beaucoup pour tes explications, slainer68. Elles me conviennent très bien

    En fait, j'essaye de passer du PHP (où j'avais l'abitude de tout faire "à la main" en partant de 0) à Ruby via la très pratique application RoR, en grande partie pour gagner du temps, mais aussi parce que le code est plus sympatique (surtout lorsqu'il faut le mettre à jour).
    Maintenant que je ne suis plus dans le flou, je vais donc pouvoir continuer la demystification, bien qu'au début ça soit assez tendu (et très frustrant ).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Pb persistance TOMCAT / MySQL
    Par killerock35 dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 07/02/2007, 11h19
  2. [MySQL] [débutant] Liste et table mysql
    Par Maria1505 dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 06/12/2006, 23h27
  3. [MYSQL] [débutant] utiliser replace avec mysql.pas
    Par alex01pernot dans le forum Bases de données
    Réponses: 2
    Dernier message: 30/08/2006, 21h23
  4. [débutant] Problème de liaison un à plusieurs
    Par Anthony17 dans le forum Access
    Réponses: 7
    Dernier message: 02/05/2006, 14h11
  5. Liaison MySQL et SQL Server
    Par Zebulonn dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 04/05/2005, 16h14

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