class Users < ActiveRecord::Base
has_many :meetings, :through => :meeting_participations
has_many :meeting_participations
end
class Meetings < ActiveRecord::Base
has_many :users, :through => :meeting_participations
has_many :meeting_participations
end
class MeetingParticipations < ActiveRecord::Base
belongs_to :user
belongs_to :meeting
scope :hidden, where(:hidden => true)
scope :visible, where(:hidden => false)
end
hidden
ist eine zusätzliche boolesche Spalte in der m2m-Zuordnungstabelle. Angesichts einer Users
-Instanz current_user
möchte ich das tun
current_user.meetings.visible
dadurch wird eine Sammlung von Meetings
abgerufen, für die der Benutzer ein Teilnehmer ist, wobei die hidden
-Spalte false
ist. Am nächsten habe ich der Meetings
-Klasse den folgenden Bereich hinzugefügt
scope :visible, joins(:meeting_participations) & MeetingParticipation.visible
scope
filtert Meetings
nach der MeetingParticipations
-Tabelle. Es gibt jedoch keine Verknüpfung/Bedingung für die MeetingParticipations
-Tabelle, die sich auf current_user
bezieht.
Das Problem dabei ist, wenn current_user
und another_user
beide Teilnehmer für eine Meetings
-Instanz sind, wird ein Meetings
-Datensatz in der Ergebnismenge für jeden Teilnehmer zurückgegeben, für den hidden
auf false
gesetzt ist. Wenn current_user
true
für hidden
für alle Meetings
festgelegt ist und falls another_user
an denselben Meetings teilnimmt, bei denen hidden
auf false
gesetzt ist, werden diese Meetings
-Ergebnisse in der Ergebnisgruppe Meetings.visible
angezeigt.
Ist es möglich, einen Gültigkeitsbereich wie oben erwähnt zu haben, der ordnungsgemäß in die User
-Instanz aufgenommen wird? Wenn nicht, kann jemand eine Lösung dafür empfehlen?
Dies ist meine Lösung für Ihr Problem:
class User < ActiveRecord::Base
has_many :meeting_participations
has_many :meetings, :through => :meeting_participations do
def visible
where("meeting_participations.visible = ?", true)
end
end
end
@user.meetings.visible
In Rails 4 können Sie den ursprünglich im untergeordneten Objekt definierten Bereich in der Assoziation angeben. Kurz gesagt: Sie müssen die Internen des MeetingParticipation-Modells im Benutzermodell nicht kennen.
class User < ActiveRecord::Base
has_many :meeting_participations
has_many :meetings, :through => :meeting_participations
has_many :visible_participations, -> { visible }, :class_name => 'MeetingParticipation'
has_many :visible_meetings, :source => :meeting, :through => :visible_participations
end
class Meeting < ActiveRecord::Base
has_many :meeting_participations
has_many :users, :through => :meeting_participations
end
class MeetingParticipation < ActiveRecord::Base
belongs_to :user
belongs_to :meeting
scope :hidden, -> { where(:hidden => true) }
scope :visible, -> { where(:hidden => false) }
end
Dies würde Ihnen Folgendes ermöglichen: user1.visible_meetings
und user2.visible_meetings
mit unterschiedlichen Ergebnissätzen
current_user.meetings.merge(MeetingParticipations.visible)
Ich weiß, dass diese Frage vor einiger Zeit beantwortet wurde, aber ich bin gerade auf ein ähnliches Problem gestoßen und habe mich nach dem besten Weg umgesehen, damit umzugehen. Die akzeptierte Lösung ist sehr einfach, aber ich denke, es wäre sauberer, wenn Sie den Assoziationsbereich von Users
auf Meeting
verlagern würden, wie im Folgenden beschrieben
class Users < ActiveRecord::Base
has_many :meetings, :through => :meeting_participations
has_many :meeting_participations
end
class Meetings < ActiveRecord::Base
has_many :users, :through => :meeting_participations
has_many :meeting_participations
scope :hidden, -> { where('meeting_participations.hidden = ?', true) }
scope :visible, -> { where('meeting_participations.hidden = ?', false) }
end
class MeetingParticipations < ActiveRecord::Base
belongs_to :user
belongs_to :meeting
scope :hidden, where(:hidden => true)
scope :visible, where(:hidden => false)
end
Mit diesem können Sie current_user.meetings.hidden
aufrufen
Die Besprechung legt nun fest, wie sie ausgeblendet/sichtbar gemacht werden soll.
Die saubere Assoziationsweise lautet:
has_many :visible_meetings, -> { merge(MeetingParticipations.visible) },
:source => :meeting, :through => :meeting_participations
Um es allgemeiner zu fassen: Wenn Sie eine verkettete has_many
-Verknüpfung haben, können Sie die Zwischenverbindung (through
) durch Zusammenführen des Bereichs einschränken. Benötigt wahrscheinlich Rails 4+.
Andernfalls müsste dies durch Erstellen einer (wahrscheinlich unerwünschten) Assoziation mit mittlerem Geltungsbereich erfolgen, wie in der Antwort von @Paul Pettengill dargestellt.
Hier ist ein One-Liner:
Meeting.joins(:meeting_participations).where(meeting_participation: { hidden: false, user_id: current_user.id })
Das ist großartig, weil Sie daraus einen Bereich erstellen, eine Funktion daraus machen oder einfach irgendwo anrufen können. Sie können dem Hash auch weitere Einschränkungen hinzufügen, die Sie möchten.