Programing

: has_many : through 연관에 조인이있는 범위

crosscheck 2020. 11. 14. 09:54
반응형

: has_many : through 연관에 조인이있는 범위


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

hiddenm2m 연관 테이블 내의 추가 부울 열입니다. 어떤 Users경우를 감안할 때 current_user, 나는하고 싶다.

current_user.meetings.visible

열이 Meetings있는 사용자가 참여자 인 컬렉션을 검색합니다 . 내가 얻은 가장 가까운 것은 클래스에 다음 범위를 추가하는 것입니다.hiddenfalseMeetings

scope :visible, joins(:meeting_participations) & MeetingParticipation.visible

scope필터하지 MeetingsMeetingParticipations에 테이블, 그러나 어떤이 가입되어 / 상태를 MeetingParticipations관련 테이블 current_user.

이것에 대한 문제는 경우입니다 current_useranother_user두 참가자가 일부 있습니다 Meetings예를하는 Meetings결과 집합의 기록이있다 각 참가자에 대해 반환됩니다 hidden설정 false. 경우 current_usertrue설정 hidden모두를 위해 Meetings, 경우 another_user에 그 같은 회의의에 참여하고 hidden로 설정 false, 사람들은 Meetings에 나타납니다 Meetings.visible결과 집합.

위에서 언급했듯이 User인스턴스 에 적절하게 조인 할 범위를 가질 수 있습니까? 그렇지 않은 경우 누군가 이에 대한 해결책을 추천 할 수 있습니까?


이것은 귀하의 문제에 대한 나의 해결책입니다.

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


Rails 4에서는 연관 자체의 자식 객체에 원래 정의 된 범위를 지정할 수 있습니다. 간단히 : 사용자 모델 내에서 MeetingParticipation 모델의 내부를 알 필요가 없습니다.

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

이것은 당신이 할 수 있습니다 : user1.visible_meetings그리고 user2.visible_meetings다른 결과 세트


current_user.meetings.merge(MeetingParticipations.visible)

이를 수행하는 깨끗한 연결 방법은 다음과 같습니다.

has_many :visible_meetings, -> { merge(MeetingParticipations.visible) },
  :source => :meeting, :through => :meeting_participations

좀 더 일반적인 용어로 표현하자면 : 연결 has_many연결이있는 경우 범위 through병합을 통해 중간 ( ) 연결 범위를 지정할 수 있습니다 . 아마도 Rails 4+가 필요합니다.

그렇지 않으면 @Paul Pettengill의 답변에서 볼 수 있듯이 (아마도 원치 않는) 중간 범위 연결을 생성하여 수행해야합니다.


다음은 하나의 라이너입니다.

Meeting.joins(:meeting_participations).where(meeting_participation: { hidden: false, user_id: current_user.id })

This is great because you can make a scope out of it, a function out of it, or simply call it anywhere. You can also add any more restrictions you want to the hash.


I know this question was answered a while back but I just encountered a similar issue and was looking around for the best way to handle this. The accepted solution is very simple but I think would be cleaner by moving the scope of the association from Users to Meeting as should below

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

With this, you are able to call current_user.meetings.hidden

By design, the meeting now dictates what make it hidden/visible.


It would seem to me that it is not sensible to use a scope on Meeting for your purpose. A meeting itself has no visibility, but the participation has. So I would suggest an extension on the association within User:

class User < ActiveRecord::Base
  has_many :meetings, :through => :meeting_participations do
    def visible
      ids = MeetingParticipation.
        select(:meeting_id).
        where(:user_id => proxy_owner.id, :visible => true).
        map{|p| p.meeting_id}
      proxy_target.where("id IN (?)", ids)
    end
  end
  ...
end

I hope, this helps.


You could also do:

current_user.meeting_participations.visible.map(&:meeting)

참고URL : https://stackoverflow.com/questions/5856838/scope-with-join-on-has-many-through-association

반응형