2011-03-16 2 views
12
class Person < ActiveRecord::Base 
    has_many :pets 

    scope :with_dog, join(:pets).where("pets.type = 'Dog'") 
    scope :without_pets ??????????????????????????????????? 
end 

class Pet < ActiveRecord::Base 
    belongs_to :people 
end 

애완 동물이없는 사람을 반환하는 범위를 Person 모델에 추가하고 싶습니다. 어떤 아이디어? 나는 이것이 명백한 것처럼 느낀다. 그러나 그것은 나를 지금 벗어나고있다. 이 같은레일에 연결된 레코드가없는 레코드 찾기 3

답변

8

시도 뭔가 :

Person.joins('left outer join pets on persons.id=pets.person_id'). 
     select('persons.*,pets.id'). 
     where('pets.id is null') 

나는 그것을 테스트하지 않은했지만 작동해야한다.

우리는 왼쪽 외부 조인을 수행하므로 애완 동물이없는 모든 사람에 대해 애완 동물 필드가 null이됩니다. join()에 문자열이 전달되면 ActiveRecord가 읽기 전용 객체를 반환하기 때문에 조인트에 :readonly => false을 포함해야 할 수 있습니다. '조인'에 '참여'에서 쿼리 메소드 이름 수정 : 당신의 애완 동물 모델은 사람의 ID를 가지고 있지만, 어쩌면이 시도가 어떻게 든

scope :with_dog, joins(:pets).where("pets.type = 'Dog'") 
scope :without_pets, joins(:pets).where("pets.person_id != persons.id") 

업데이트를 도움이된다면

+0

결과 SQL : 여기 내가 사용하는 코드의 개조 버전입니다. 사람을 선택 *,'왼쪽 persons' 외부로부터 pets.id 어디 persons.id = pets.person_id WHERE'persons' 애완 동물을 가입 할 수 있습니다. 'deleted' = 0 AND (pets.id가 null 임) – Shagymoe

+0

죄송합니다! 나는 그 조인을 잘못 입력했다. "... person.id = pets.person_id"가 아니라 "... person.id = ..."가 아니어야합니다. –

+0

select ('persons. *, pets.id')에 ", pets.id"가 필요합니까? LEFT OUTER JOIN은 'includes'의 목적이 아니지만 select ('persons. *, pets.id as pet_id') – mkirk

5

Mark Westling의 답변이 맞습니다. 외부 조인은 올바른 방법입니다. 내부 조인 (조인 메서드가 생성 한 조인 메서드는 사용자가 자신의 SQL이 아닌 연관의 이름/심볼을 전달 함)은 작동하지 않습니다. 애완 동물이없는 사람들은 포함되지 않기 때문입니다.

다음

그것은 범위로 기록됩니다. (그래도 문제가 해결되지 않으면, '사람'과 '사람'을 대체하려고 - 나는 당신의 테이블 이름이 무엇인지 확실하지 않다)

scope :without_pets, joins("left outer join pets on pets.person_id = persons.id").where("pets.id is null") 

21
scope :without_pets, lambda { includes(:pets).where('pets.id' => nil) } 
+0

과 같이 열을 별칭으로 지정하지 않으면 persons.id와 충돌 할 가능성이 있습니다. 조합 쿼리가 LEFT OUTER JOIN이됩니다. – lulalala

+2

목적에 상관없이 작동합니다. 더 적은 필기 SQL 대답 = 나는 그것이 더 좋다고 생각한다. –

1

관련 레코드가없는 레코드를 찾으려면 LEFT OUTER JOIN을 사용해야합니다. 실패

scope :without_pets, joins('LEFT OUTER JOIN pets ON people.id = pets.person_id').group('people.id').having('count(pets.id) = 0') 
관련 문제