Accueil
Actualités
Liste des jeux vidéo
Critiques
Hors-jeu !
Gribouillages
Whois?


Rails 2.3.2 && Ruby 1.8.7
Imaginons une petite application tout bête pour enregistrer des projets et les membres qui y participent dans une base de données. Les membres peuvent être sur différents projets et les projets peuvent avoir plusieurs membres. Pour simplifier le tutoriel, on n'enregistre que le nom du projet et le pseudo du membre.
Ce petit tuto sans prétention explique comment procéder pas à pas. Il implique tout de même que vous sachiez créer un projet et configurer le fichier database.yml dans le répertoire config.
On va utiliser l'échafaudage pour créer... pratiquement tout ce dont on a besoin : les modèles, les controllers, les vues et la base des formulaires.
puis
Attention :
Le nom du modèle doit commencer par une majuscule et être un mot au singulier. Tous les types des propriétés (nom et pseudo) commencent par une minuscule. La création de la table, plus tard, ne fonctionnera pas s'il y a des majuscules qui trainent.
On va ensuite connecter les deux modèles. On a dit que chaque projet peut avoir plusieurs membres et chaque membre peut participer à plusieurs projets. C'est le parfait exemple d'une relation has_and_belongs_to_many.
On modifie donc les deux modèles (membre.rb et projet.rb dans app/model) :
Attention : notez que le nom du modèle est au pluriel.
Ce genre de relation exige ce qu'on appelle une table de jointure. C'est une nouvelle table dans la base de données qui enregistre chaque couple. A chaque fois qu'un nouveau membre s'inscrit à un projet, une nouvelle ligne est créée dans cette table.
Rails possède une convention de nommage pour les tables de jointure : il faut appeler cette table du nom des modèles concernés (pour nous : membre et projet) au pluriel, dans l'odre alphétique, séparés par un underscore.
Notre table s'appellera donc membres_projets
Pour créer la migration qui créera la table dans la base :
On retrouve ce fichier dans le répertoire db/migration. Il faut le construire de cette manière :
Attention :
:id => false est très important. S'il n'y est pas, la table ne peut pas fonctionner. En effet, une table de jointure n'a pas d'index incrémenté automatiquement à chaque nouvelle entrée et n'a donc pas d'id.
Enregistrez le tout. Il est temps de construire les tables :
Pour la suite des évènements, testez le tout et créez quelques membres et quelques projets.
Puis rendez vous sur http://localhost:3000/membres et http://localhost:3000/projets
Il va ensuite falloir inscrire les membres aux projets par le biais des formulaires.
Dans le controller des membres, on se met la liste des projets à disposition pour les vues, et ce dans l'ordre alphétique - tant qu'à faire - pour les retrouver plus facilement.
Puis, dans la vue (app/views/membres/edit.erb.html), on ajoute la formule magique pour créer la balise select à choix multiple :
Le paramètre prompt est facultatif et permet simplement d'avoir une ligne de texte (ou vide) sans valeur associée.
Le paramètre multiple est celui qui permet de faire plusieurs choix dans la liste. Si on l'omet, on se retrouve avec un menu déroulant.
Maintenant, il faut afficher tout ça. On doit pouvoir consulter qui sont les membres inscrits à un projet et quels sont les projets auxquels un membre est inscrit.
Pour les membres (app/views/membres/show.erb.html) :
Et pour les projets (app/views/projets/show.erb.html) :
Et voilà !
Lily, le 21 June 2011
Je ne peux pas vous aider sans voir votre code. Je confirme que le tuto ci-dessus fonctionne, c'est encore la méthode que j'utilise.
Pour répondre à vos questions :
1) les tables de jointures sont en effet automatiquement mises à jour grâce aux conventions de nommage (d'où l'importance de nommer la table de jointure correctement : nom des deux tables au pluriel par ordre alphabétique)
2) le paramètre :multiple => true fonctionne sous tous les navigateurs courants (IE, FF, Safari, Opera et Chrome chez moi, mais je ne teste pas sous toutes les versions de chaque navigateur. Néanmoins, c'est un paramètre qui se traduit par un simple code HTML.
3) NoMethodError in ProductsController#update semble laisser entendre qu'il y a un problème dans votre controller Products. En général, les méthodes "create" et "update" n'ont pas besoin d'être modifiées, en tout cas pas dans le cadre du tuto ci-dessus. Vous pourriez aussi vous assurer que les routes sont correctes si vous n'avez pas généré vos controlleurs avec un scaffold (si vous avez généré un controller uniquement, les routes ne sont pas configurées automatiquement pour vous)
La plupart du temps, lorsqu'il y a une typo dans le code d'une relation habm, l'enregistrement ne s'effectue pas, tout simplement.
Bon courage.
TotorZ, le 22 September 2011
Dans la migration, remplacer :
drop_table : membres_projets
par
drop_table :membres_projets
C'est pas grand chose mais ça évite l'erreur au rollback
Merci pour le tuto ;)
TotorZ, le 22 September 2011
C'est encore moi ! C'est cette migration qui me chagrine.
Il manque les index, et aussi la nouvelle syntaxe Rails.
Peut être que certains préfèreront donc :
class CreateMembresProjects < ActiveRecord::Migration
def change
create_table :membres_projects, :id => false do |t|
t.references :membre
t.references :project
t.timestamps
end
add_index :membres_projects, [:membre_id, :project_id]
end
end
Laissez un p'tit mot !
~ Protégez-vous du hameçonnage - 27/04/2010
~ Windows 7 : afficher les dossier et fichiers cachés - 20/04/2010
~ Ruby on Rails - le modèle has_and_belongs_to_many - 01/02/2010
~ Tablette graphique et Gimp sous Ubuntu : pression et gomme - 27/09/2009
~ Numériser une image avec The Gimp sous Linux - 19/08/2009
~ Installer une imprimante sous Linux - Ubuntu - 17/08/2009
~ Installer Ruby on Rails sur Linux - Ubuntu - 10/08/2009
~ Input & textarea : attention aux couleurs ! - 30/07/2009
~ Personnaliser son bureau avec Ubuntu - 26/07/2009
~ Installation de Linux Ubuntu 9.04 - 25/07/2009
Bonjour,
le tuto est bien écrit, mais il ne fonctionne pas...
Je vois le menu déroulant contenant les choix possibles mais impossible de sauver. Il me semble que le tuto n'indique pas comment mettre à jour la table de jointure ?? (ou bien est-ce automatique)
Voici l'erreur, incompréhensible et sans numéro de ligne :
NoMethodError in ProductsController#update
undefined method `reject' for "2":String
De plus, le paramètre :multiple=>true ne génère qu'un simple menu déroulant sous Chrome 6. Est-ce normal ?
Merci pour les infos