2010-11-16 3 views
1

Pour simplifier les choses, j'ai 3 tables:Ruby on Rails - Sauvegarde et mise à jour d'un attribut dans une table de jointure avec a beaucoup => par

Personne

has_many: capacités, à travers =>: stats

Capacité

has_many: les gens, à travers =>: Statistiques

Statistiques

belongs_to: personnes

belongs_to: capacités

Stats a un attribut supplémentaire appelé 'qualification'. Ce que je voudrais faire est de faire un formulaire d'édition de personne qui énumère toujours toutes les capacités actuellement dans la base de données, et me laisse attribuer une évaluation.

Pour la vie de moi, je ne peux pas comprendre comment faire ceci. J'ai réussi à le faire fonctionner lors de la création d'un nouvel utilisateur avec quelque chose comme ceci:

(du contrôleur de personnes)

def new 
@character = Character.new 
    @abilities = Ability.all 
    @abilities.each do |ability| 
     @person.stats.build(:ability_id => ability.id) 
    end 
end 

From the people form: 

<% for @ability in @abilities do %> 
    <%= fields_for "person[stats_attributes]" do |t| %> 
<div class="field"> 
    <%= t.label @ability.name %> 
    <%= t.hidden_field :ability_id, :value => @ability.id, :index => nil %> 
    <%= t.text_field :rating, :index => nil %> 
    </div> 
    <% end %> 
    <% end %> 

Cela me donne avec succès une liste des capacités avec des boîtes de notation à côté d'eux, et permet de les enregistrer si je fais un nouvel utilisateur. Le problème est que si je charge ensuite le formulaire d'édition (en utilisant le même formulaire partiel), il ne ramène pas les évaluations, et si je sauvegarde, même avec exactement les mêmes évaluations, il crée des entrées en double dans la table de statistiques, au lieu de la mettre à jour. Je réalise que je suis un mauvais programmeur et je le fais probablement dans le mauvais sens, mais comment puis-je obtenir le formulaire d'édition pour rappeler les évaluations actuelles attribuées à chaque capacité pour cet utilisateur, et deuxièmement comment puis-je obtenir -il mettre à jour la notation au lieu de la dupliquer si la combinaison de personne et de capacité existe déjà?

Répondre

0

Railscasts épisodes 196 et 197 montrent comment éditer plusieurs modèles dans un formulaire. Exemple montré là-bas ressemble à ce que vous essayez de faire afin qu'il puisse vous aider (mêmes épisodes sur les ascicasts: 196, 197).

1

pas Si tel était

Character 
has_many :stats 
has_many :abilities, through => :stats 

Ability 
has_many :stats 
has_many :characters, through => :stats 

Stat 
belongs_to :character 
belongs_to :ability 

?

Aussi, est-ce une personne ou un personnage? Vous parlez diversement aux deux. (Je vais aller avec Caractère dans ma réponse)

Je pense que vous êtes tombé sous le coup de "Je vais essayer de faire une version simplifiée de mon schéma afin d'essayer d'illustrer un problème, mais faites plutôt les choses plus complexes et embrouiller le problème en le vissant de sorte qu'il n'a pas de sens "syndrome". Quoi qu'il en soit, il y a quelques problèmes que je peux voir:

1) La première chose est que vous ajoutez toutes les capacités possibles à un personnage dès qu'elles sont créées.C'est idiot - ils devraient commencer sans aucune capacité par défaut et ensuite vous créez des enregistrements de table de jointure (stats) pour ceux qu'ils ont do avoir (en cochant les cases dans le formulaire).

2) Une façon simple de manipuler joindre des dossiers comme celui-ci est de tirer parti de la méthode « ability_ids = » que le has_many: capacités macro vous donne - appelé « collection_ids = » dans le api http://railsbrain.com/api/rails-2.3.2/doc/index.html?a=M001885&name=has_many

Dans d'autres mots, si vous dites

@ character.ability_ids = [1,12,30]

alors qui fera entre ce personnage joint et les capacités 1, 12 et 30 et supprimer toute autre jointures entre ce caractère et les capacités pas dans la liste ci-dessus. Combinez cela avec le fait que les noms de champ de formulaire se terminant par [] mettre leurs valeurs dans un tableau, et vous pouvez faire ce qui suit:

#controller 
def new 
@character = Character.new 
@abilities = Ability.all 
end 

#form 
<% @abilities.each do |ability| %> 
    <div class="field"> 
    <%= t.label @ability.name %> 
    <%= check_box_tag "character[ability_ids][]" %> 
    </div> 
<% end %> 

#subsequent controller (create action) 
@character = Character.new(params[:character]) #totally standard code 

avis qu'il n'y a aucune mention de statistiques ici du tout. Nous spécifions les associations que nous voulons entre les caractères et les capacités et laissons les rails gérer les jointures.

Questions connexes