webentwicklung-frage-antwort-db.com.de

Umfang mit join on: has_many: durch Assoziation

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_usertrue 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?

60
deefour

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

78
Andrei Erdoss

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

59
Paul Pettengill
current_user.meetings.merge(MeetingParticipations.visible)
7
woto

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.

0
Abass Sesay

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.

0
thisismydesign

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.

0
Mirror318