6
votes

Comment mettre à jour une collection HAS_AND_BELONGS_TO_MANY?

J'ai deux modèles générés par un échafaudage, étudiant et classe . Ils ont une relation plusieurs à plusieurs mises en œuvre avec HAS_AND_BELONGS_TO_MANY.
J'aimerais pouvoir changer quelle classe ES A Student est dans aussi bien que ce que étudiant S est en train de prendre chaque classe . C'est-à-dire que je veux modifier un étudiant Student 'S variable (ajouter et supprimer des éléments de celui-ci) et inversement.
Comment puis-je faire cela repose?
Si je retire une classe à partir d'un étudiant classes , il semble que je veux appeler mise à jour sur mes étudiants_controller. Si tel est le cas, alors que dois-je passer sous forme de paramètre pour modifier la variable classes ? Une autre collection de classe ES (avec la classe supprimée)?
Mon autre pensée est juste d'appeler une certaine action dans les étudiants_controller (disons, retirer_class) et transmettre l'identifiant de la classe à supprimer. Cela semble sensical mais pas reposant.

Quelle est la meilleure façon de faire cela?


0 commentaires

5 Réponses :


0
votes

Si cela est vraiment reposé, vous changeriez simplement la classe et l'élève en même temps, en ajoutant la relation à la fois ou en le supprimant des deux. Après avoir vérifié que le modèle téléchargé était auto-cohérent, vous le comparez ensuite à l'encontre de la précédente et de faire les changements nécessaires. Si ce changement est entraîné par catégorie ou que l'étudiant devient un détail de mise en œuvre.

Deux autres options:

Vous pouvez rendre les informations sur l'état de repos moins redondantes, en laissant la classe ou l'élève de la relation, mais cela ne correspond peut-être pas à vos besoins.

Vous pouvez également conserver les informations de relation des deux côtés, mais décidez que l'on est canonique. Ainsi, par exemple, si l'étudiant appartient à la classe, pas l'étudiant, alors tout changement à l'étudiant appartient à l'élève est ignoré.

Je préfère la première option, mais je pense que ceux-ci devraient être au moins pris en compte.


0 commentaires

0
votes

Je ne suis pas sûr de vouloir faire les deux de manière robuste. Vous auriez probablement plus de kilométrage en créant une relation de suppression en cascade entre les deux.

Voici une discussion sur Suppression de cascade sur les rails .


0 commentaires

0
votes

Vous pouvez avoir deux ressources imbriquées?

dépendez de savoir si vous avez un paramètres [: class_id] code> (veuillez ne pas dire que vous avez appelé votre classe modèle!) Ou si vous aviez un Params [: Student_ID] CODE> Vous pouvez dire lequel est l'objet que l'opération est appelée (voir Sample Création ci-jointe d'un côté): P>

class SchoolClassController < ApplicationController

before_filter :get_school_class, :except => [:new, :create, :index]
before_filter :get_student

def create
  get_school_class(false)
  get_student(false)
  if @school_class
    if @student
      (@school_class.students << @student)
    else
      redirect_to "/" and return
    end
  else
    @school_class = SchoolClass.new(params[:school_class])
  end
  if @school_class.save
    redirect_loc = @student ? student_school_class_path(@student, @school_class) : school_class_path(@student)
    redirect_to redirect_loc and return
  else
    redirect_to "/"
  end

end

private

def get_school_class(will_redirect=true)
  begin
    @school_class = SchoolClass.find(params[:id])
  rescue AR::RNF
    (redirect_to "/" and return false) if will_redirect
  end
end

def get_student(will_redirect=true)
  if params[:student_id]
    begin
      @student = Student.find(params[:student_id])
    rescue AR:RNF
      (redirect_to "/" and return false) if will_redirect
    end
  end
end

end


0 commentaires

9
votes

La touche pour résoudre ce problème consiste à identifier correctement la ressource que vous modifiez. Dans ce cas, la ressource que vous modifiez est la relation entre la classe et l'étudiant, que je me référerai comme une inscription .

Il est devenu habituel dans des rails d'utilisation has_many : via préférentiellement à has_and_belongs_to_many . Vous voudrez peut-être modifier votre logique de domaine pour vous adapter à la coutume, mais vous pouvez également endommager la tendance, si vous êtes vraiment certain qu'aucune métadonnée n'a besoin d'être stockée sur la relation.

une des idées clés pour Le repos est que des ressources reposantes n'ont pas besoin de cartographier des modèles. Vous devez créer un inscrivez-vousController et ajoutez une ligne à config / routtes.rb: xxx

alors vous pouvez créer et supprimer vos relations comme: < / p> xxx

et vous pouvez créer des boutons pour ces actions comme: xxx

1 sur La ligne ci-dessus agit comme un espace réservé où le : inscription_id devrait aller et est un peu de vinaigre syntaxique pour vous rappeler que vous collez la volonté du cadre des rails.


2 commentaires

Merci, cela a très bien fonctionné avec deux changements mineurs: 1. Appeler @ Student.Courses.Destroy (Params [: Course_id]) m'a donné un ACTiverecord :: AssociationTyPamismatic, car il cherchait bien sûr et obtenu une chaîne. J'ai réparé cela en trouvant d'abord le bon parcours (@ étudiant.courses.find (Params [: cours de cours])), puis en supprimant cela. 2. Je ne veux pas détruire le cours, simplement supprimer l'association, donc j'ai utilisé un appel de suppression au lieu de détruire


Heureux que ça ait travaillé. J'ai mis à jour mon exemple pour refléter vos modifications.



0
votes

Il existe une variété de méthodes ajoutées lorsqu'il indique un nombre élevé à plusieurs relations (17 à être exact) selon les rails 6.1.0

Selon ce que vous recevez de votre extrémité frontale, étant l'objet d'un objet associé ou simplement leurs identifiants, vous voudrez appeler différentes méthodes:

Utilisation d'un tableau de l'ensemble des objets associés: collection_plural =

I.e: @Student. classes = new_student_classes_array

Recevoir une gamme de clés principales d'objets associés (Habituellement IDS): Collection_singular_ids =

I.e: @Student. class_ids = new_student_classes_array


0 commentaires