문제

나는 레일에 초보자이며 MySQL에서 왼쪽 가입을 수행하려고합니다.

사용자와 메시지의 두 가지 객체가 있습니다.

사용자 has_and_belongs_to_many 메시지, 메시지 has_and_belongs_to_many 사용자

현재, 단순히 user.messages를 작성하면 콘솔에서 쿼리를 따릅니다.

SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1 )

제한된 메시지가있는 메시지가있는 메시지가 사용자에게 연결되어 있지 않지만 사용자가 액세스 할 수 있으며 user.messages에 수집 메시지를 추가해야합니다.

내 문제를 해결할 쿼리는 다음과 같습니다.

select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true);

가능한 한 우아하게 레일에 쓰는 방법은 무엇입니까?

smth와 같은 것입니다

Message.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 " )

아니면 더 좋을 수 있습니까?

나는 Rails 2.3.2를 사용하고 있습니다

고마워요, 파벨

도움이 되었습니까?

해결책

그 쿼리에서 두 가지를 가져 오려고하는 것 같습니다. 1) 모든 메시지가 제한된 = false 및 2) 모든 메시지가 제한된 = true를 가진 현재 사용자에게 묶여 있습니다.

내가 그것을 올바르게 이해하고 있다면, 당신이 그것을 단일 쿼리로 만들고 싶다면 더 좋은 방법을 보지 못합니다. 그러나 두 쿼리를 만들 겠다는 아이디어에 열려있는 경우 코드에서 약간 정리할 수 있습니다 (실행 속도를 늦출 수 있음). 대체 설정은 다음과 같습니다.

class Message < ActiveRecord:Base
  has_and_belongs_to_many :users

  named_scope :restricted, :conditions => {:restricted => true}
  named_scope :unrestricted, :conditions => {:restricted => false}
  named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM messages_users)"
end

class User < ActiveRecord:Base
  has_and_belongs_to_many :messages
end

코드가 적지 만 두 개의 데이터베이스 히트가 필요한 목록을 얻으려면 다음을 수행 할 수 있습니다.

@current_user.messages.restricted + Message.unrestricted.public

두 경우 모두이 테이블에 상당한 양의 데이터가 있으면 적절하게 색인화되어 있는지 확인해야합니다. 이것이 많은 메시지가 전송되는 앱이라면 단일 쿼리가 더 나을 것입니다. 많이 사용되지 않는 측면 기능이라면 클리너 버전을 가져갈 것입니다.

모델 관점에서 더 잘 작동하는 것은 HABTM 관계를 없애고 관계를 명시 적으로 모델링하는 것입니다. 그런 다음 메시지 전송/배송/수신 프로세스 (전송 시간 추적 시간, 시간 읽기 등)에 대한 다른 데이터를 추적 할 수있는 편리한 장소가 있습니다. 위의 토론을 바꾸지 않고 HABTM에 대한 많은 사람들이 선호합니다.

class Message < ActiveRecord:Base

  has_many :subscriptions
  has_many :users, :through => :subscriptions

  named_scope :restricted,   :conditions => {:restricted => true}
  named_scope :unrestricted, :conditions => {:restricted => false}
  named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM subscriptions)"
end

class User < ActiveRecord:Base

  has_many :subscriptions
  has_many :messages, :through => :subscriptions

end

class Subscription < ActiveRecord:Base

  belongs_to :message
  belongs_to :user

end

다른 팁

사용하지 않는 이유 : 포함?

나는 이름의 _scopes가 당신의 대답일지도 모른다고 생각합니다. 모델에서 다음과 같은 내용을 넣습니다.

named_scope :restricted,   :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}

그런 다음 다음과 같은 것을 부를 수 있습니다.

Message.restricted
=> All restricted messages

User.first.messages.unrestricted
=> All unrestricted messages belonging to the first user.

나는이 작업이 HABTM 협회를 통해 믿는다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top