2016-03-29 11 views
0

Ich habe eine Join-Tabelle, die einem Client- und einem Setor-Modell (Plural: setores) beitritt. Die Beziehung ist, dass ein Client has_and_belongs_to_many Setores (es gibt drei Setores, ein Client kann von einem bis alle drei haben. Setoren haben viele Clients).Zusätzlicher Fremdschlüssel für eine Join-Tabelle

Mein Problem ist: In dieser Join-Tabelle habe ich einen Verweis auf das Benutzermodell hinzugefügt. Setoren haben viele Benutzer, aber eine Beziehung zwischen einem Client und einem Setor hat nur einen Benutzer. Aber ich weiß nicht, wie diese Zuordnung in der Tabelle clients_setores lesen und schreiben.

Meine Modelle sind wie folgt:

class Client < ActiveRecord::Base 
has_and_belongs_to_many :documents 
has_and_belongs_to_many :setores 
has_many :screenings 
has_many :contacts 
has_many :interactions, through: :contacts 
validates :cnpj, uniqueness: true 


class Setor < ActiveRecord::Base 
    self.table_name = 'setores' 
    has_many :documents 
    has_many :screenings 
    has_many :users 
    has_and_belongs_to_many :clients 
    attr_acessor :user_id 


class User < ActiveRecord::Base 
has_one :setores 
has_many :clients 

Und die aktuelle Tabellen-Parameter verbinden, die so gearbeitet haben am Ende des Clients Controller angezeigt:

private 
# Use callbacks to share common setup or constraints between actions. 
def set_client 
    @client = Client.find(params[:id]) 
end 

# Never trust parameters from the scary internet, only allow the white list through. 
def client_params 
    params.require(:client).permit(:cnpj, :pacote, :razsoc, :vencimento, user_ids:[], document_ids:[], setor_ids:[]) 
end 

Beachten Sie, dass „benutzerkennungen: [ ] "war mein Versuch, es zur Arbeit zu bringen, was bisher gescheitert ist.

In den Ansichten ich die aktuelle verwende Join-Tabellen wie folgt (von /client/_form.html.erb genommen):

<%= f.collection_check_boxes :setor_ids, Setor.where(pacote: true), :id, :setor do |b| %> 

Also mit diesem Kontrollkästchen kann ich einen Eintrag in der clients_setores Tabelle erstellen.

Was ich tun möchte ist in der Lage, einen Benutzer, der zu einer bestimmten Setor_id gehört, aus einem Dropdown-Menü auswählen und diese Beziehung in der Join-Tabelle speichern. Ich habe es geschafft, zu solchen Menü mit dem folgenden Code erscheinen, in der gleichen _form.html.erb:

<%= f.collection_select :user_ids, User.where(:setor_id => 1), :id, :email %> 

Aber wenn ich das Formular abschicken, werden die Werte nicht gespeichert. Ich weiß nicht, ob mein Problem nur darin besteht, dass ich nicht den richtigen Weg gefunden habe, diese Assoziation aus meiner Sicht aufzunehmen, oder ob mein Problem weiter unten im Controller (wahrscheinlich) und im Modell (vielleicht) liegt.

Das nächste Problem, das ich in SO fand, war Rails 4 Accessing Join Table Attributes, aber der Zuordnungstyp ist anders (has_many/through) und es gibt keine dritte Beziehung beteiligt, so dass ich nicht herausfinden konnte, wie es für mich funktioniert.

+0

Hey, ich habe deine Frage nicht ganz verstanden, wenn du erklären könntest, was du meinst "Mein Problem ist: In dieser Join-Tabelle habe ich einen Verweis auf das Benutzermodell hinzugefügt." Die Join-Tabelle für has_and_belongs_to_many lässt nur zwei zu Spalten (die Fremdschlüssel für Ihre setor- und client-Tabelle). Wenn Sie also sagen, dass Sie einen Verweis auf diese Tabelle hinzufügen möchten, müssen Sie eine "has_many through" -Einstellung verwenden. Außerdem haben Sie nicht angegeben, dass Ihr Client zu einem Benutzer in Ihrem Clientmodell gehört. – bkunzi01

+0

Damit ein Client viele Benutzer hat, müsste er über die gleiche Anzahl von Setores (1 setor: 1 client; 3 setores: 3 clients) verfügen, funktioniert die has_many/through-Beziehung so? Wie für den Client, der dem Benutzer gehört, gehört er immer zu so vielen Benutzern wie Setores; ist das relevant? –

+0

Ok, also sagen Sie, wenn ein Client einen Benutzer haben soll, muss er auch einen Setore haben? Sorry, ich bin mir immer noch nicht sicher, was du zu tun versuchst, aber wenn du einen Weg brauchst, um sicherzustellen, dass Clients und Einstellungen auch über Benutzer gleichzeitig wissen, musst du eine "has_many through" -Verbindung verwenden, damit du Sie können dieser Join-Tabelle zusätzliche Spalten hinzufügen, um die zusätzlichen Informationen für Benutzer zu speichern. – bkunzi01

Antwort

1

Beispiel für viele-zu-viele Assoziationen zwischen drei Modellen mit einer einzigen Join-Tabelle getan:

ich durch die Generierung einige Modelle beginnen:

rails g model User; rails g model Setor; rails g model Client; 
rails g model Joiner user_id:integer setor_id:integer client_id:integer 

By the way, ist references ein Weg Hinzufügen eines Fremdschlüssels, der auf ein vorhandenes Modell verweist. I.e. user:references erstellt eine user_id-Spalte. Es fügt dem Fremdschlüssel auch einen "Index" hinzu, der die Leistung verbessert.

Dann einige Assoziationen zu den Klassen

class Joiner 
    # columns: user_id, setor_id, client_id 
    belongs_to :user 
    belongs_to :setor 
    belongs_to :client 
end 

class User 
    has_many :joiners 
    has_many :setors, through: :joiners, source: :setor 
    has_many :clients, through: :joiners, source: :client 
end 

class Setor 
    has_many :joiners 
    has_many :users, through: :joiners, source: :user 
    has_many :clients, through: :joiners, source: :client 
end 

class Client 
    has_many :joiners 
    has_many :users, through: :joiners, source: :user 
    has_many :setors, through: :joiners, source: :setor 
end 

Mit diesem Code geschrieben, ich hinzufügen, haben Sie viele-zu-viele Verbände für die drei Modelle.

können Sie dann schreiben:

User.create; Setor.create; 
Joiner.create(user_id: User.first.id, setor_id: Setor.first.id); 
User.first.setors.length # => 1 

Dies wird für die Selbst schließt sich nicht (das heißt einer verschachtelten Kommentar-System), durch die Art und Weise, aber das ist nicht die Frage Teil.

+0

In diesem Fall, wo würde ich die Beziehung zwischen einem Kunden und seinem (bis zu speichern drei) UserSetor-Paarungen? –

+0

@SamOliver wahrscheinlich eine andere Join-Tabelle. 'ClientUserSetor' vielleicht. Es ist nicht schön, aber es wird den Trick machen. Schauen Sie sich übrigens die [detaillierte Assoziationsreferenz] (http://guides.rubyonrails.org/association_basics.html) an. –

+0

Ich habe Ihre erste Antwort ein paar Mal gelesen und es gab mir die Idee, ein neues Modell, sagen wir "WeirdRelation", mit einer Tabelle zu erstellen, die nur die user_id, setor_id und user_id speichern würde. Dies ist nicht, wie ich entschied, um dieses spezielle Problem zu lösen (siehe meine Antwort unten), aber das würde ich mitgehen, wenn ich mehr "Setores" pro Client hätte. –

0

Was ich den gewünschten Effekt zu tun am Ende zu erreichen, war drei Spalten Client-Modell hinzuzufügen:

Memo 1

userset2

userset3

diese Weise kann ein Kunde hat bis zu drei (da das Feld leer sein kann) Beziehungen mit Benutzern, nach den Setores (Abteilungen) hat er zu seinen Diensten.

Dies ist die einfachste Lösung in diesem Fall da ich nur 3 Setores habe. Es wäre nicht für größere Zahlen.

Wenn ich mehr als 3 Setores hatte, was es unmöglich machte, Spalten in der Client-Tabelle hinzuzufügen, würde ich ein neues Modell erstellen, nur um die Relationen zu speichern, in diesem Fall eine Tabelle, die neben ihrer eindeutigen ID hätte , client_id, setor_id und user_id.

Verwandte Themen