레일에서 ActiveRecord를 사용하여 여러 조인
-
03-07-2019 - |
문제
나는 사용자가 다른 사용자를 팔로우하고 메시지 피드를받을 수있는 작은 트위터 스타일 마이크로 블로깅 서비스를 구축하고 있습니다.
다음 모델이 있습니다.
class Follow < ActiveRecord::Base
belongs_to :follower, :class_name => "User"
belongs_to :followee, :class_name => "User"
end
class User < ActiveRecord::Base
has_many :follows, :foreign_key => 'follower_id',
:class_name => 'Follow'
has_many :followers, :through => :follows
has_many :followed, :foreign_key => 'followee_id',
:class_name => 'Follow'
has_many :followees, :through => :followed
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :user
end
현재 사용자를위한 피드를 얻으려면 다음 SQL 쿼리를 수행하고 싶습니다.
SELECT * FROM follows JOIN users JOIN messages WHERE follows.follower_id = current_user.id AND follows.followee_id = users.id AND users.id = messages.user_id;
이 작업을 수행하는 올바른 ActiveRecord 방법은 무엇입니까?
해결책
당신이 무엇을 찾고 있는지 확실하지 않지만 여기에 내 제안이 있습니다.
나는 당신이 그 다음 수업에 대한 다른 목적을 가지고 있다고 가정합니다. 그렇지 않으면 나는 그것의 목적을 보지 못합니다.
"올바른 방법"(즉, 완전히 주관적인 방법)은 실제로 다음과 같습니다.
class User < ActiveRecord::Base
has_and_belongs_to_many :followers, :foreign_key => 'followed_id',
:class_name => 'User', :association_foreign_key => 'follower_id',
:include => [:messages]
has_and_belongs_to_many :follows, :foreign_key => 'follower_id',
:class_name => 'User', :association_foreign_key => 'followed_id'
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :user
end
그런 다음 다음 표를 만듭니다.
create_table :users_users, :id => false do |t|
t.integer :followed_id
t.integer :follower_id
end
그리고 당신은 설정합니다 :
followed = User.find :first
follower = User.find :last
followed.followers << follower
followed.followers.first.messages
followed.followers.first.followers.first.messages # etc...
그러나 내가 만든 것에서, 당신은 모든 추종자들의 모든 메시지를 동시에 보여주고 싶습니다.
이것은 추가하여 달성 할 수 있어야합니다
has_and_belongs_to_many :followed_messages, :foreign_key => 'follower_id',
:class_name => 'Message', :association_foreign_key => 'followed_id'
~로 사용자 수업이지만, 그런 식으로 얼마나 올바른지 모르겠습니다. 또는 연관 확장으로 달성 할 수는 있지만 실제로는 예를 들어 볼 수 없습니다.
업데이트:다음을 변경하면 Class_name이 Message.id
, 그것에 대해 생각하지 않았으므로 이런 식으로 맞지 않을 것입니다.
따라서 유일한 "좋은"옵션은 첫 번째 예에서와 같이 사용자 클래스를 살펴 보는 것입니다. 내가 볼 수있는 유일한 옵션은 협회 확장 (예를들 수 없음) 또는 Finder 문을 사용하는 것입니다.
has_many :followed_messages, :class_name => 'Message',
:finder_sql => 'select * from messages where user_id in(select followed_id from users_users where follower_id = #{id})'
모든 것이 작동하기 위해 SQL 문을 사용자 정의해야 할 것입니다. 그러나 적어도 사진을 가져와야합니다 :)
다른 팁
Keijro의 배열은 더 잘 작동하지만 다음 테이블이 필요하면 다음과 같이 지정된 SQL 쿼리를 실행할 수 있습니다.
Follow.all(:joins => { :messages, :users }, :conditions => { "follows.follower_id" => current_user.id, "follows.followee_id" => "users.id", "users.id" => "messages.user_id"} )