Rails에서 scope / named_scope는 무엇입니까?


105

최근에 인턴십을 시작했습니다. 내 고용주는 레일에서 루비를 사용하고 있으며 이해하기 위해 찾아봐야하는 새로운 구문을 자주 접합니다. named_scope에 대한 좋은 설명을 찾기 위해 검색을 해봤지만 지금까지 찾은 것은 대부분 블로그 게시물이 칭찬을주는 것이지 직접적인 정의 나 소개였습니다.

레일 위의 루비에서 named_scope (이제 간단히 스코프라고 함)는 정확히 무엇입니까?



2
이 블로그 게시물은 명명 된 스코프를 배울 때 매우 중요했습니다. ryandaigle.com/articles/2008/8/20/…
Peter Brown

@notapatch 링크가 죽었습니다. 다른 것이 있습니까?
mbigras

라이언 Daigle은 : 범위 명명 : 그것은 그냥 조건, 나중에 알고?에 대한 아니다 web.archive.org/web/20160306110506/http://...
notapatch

답변:


212

범위는 컬렉션의 하위 집합입니다. 복잡하게 들리나요? 그렇지 않습니다. 이것을 상상해보십시오.

사용자가 있습니다. 이제 일부 사용자는 뉴스 레터를 구독하고 있습니다. 사용자 데이터베이스에 필드를 추가하여 뉴스 레터를받는 사람들을 표시했습니다 (user.subscribed_to_newsletter = true). 당연히 뉴스 레터를 구독하는 사용자를 원할 때도 있습니다.

물론 항상 다음과 같이 할 수 있습니다.

User.where(subscribed_to_newsletter: true).each do #something

그러나 항상 이것을 작성하는 대신 다음과 같이 할 수 있습니다.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Rails 4 이상을 사용하는 경우 대신 다음을 수행하십시오.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

이렇게하면 다음과 같이 간단히 구독자에 액세스 할 수 있습니다.

User.newsletter.each do #something

이것은 매우 간단한 예이지만 일반적으로 범위는 작업을 쉽게하는 매우 강력한 도구가 될 수 있습니다.

이 링크를 확인하십시오 : API 설명


7
'subscribedUsers'라는 사용자 클래스에서 메서드를 정의하는 것보다 이것의 장점이 무엇인지 물어볼 수 있습니까? 예를 들어, '데프 self.subscribedUsers self.where (: subscribed_to_newsletter => TRUE) 끝
redroot

3
@redroot 장점이있다 scope구문, 당신은 훨씬 청소기 같은 결과를 얻을 수 있지만 하나 개의 라인
알도 'xoen'Giambelluca

9
@redroot 스코프는 데이터베이스를 느리게 쿼리하는 반면 메서드는 열심히 수행하므로 효율성이 크게 향상되었습니다. Rails 3에서 메소드도 게으 르기 때문에 이제 그 차이는 더 많은 구문입니다. 출처
evanrmurphy 2013 년

API의 문서 링크하십시오 업데이트 고장 api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/...을
Lohith MV를

또한 범위가 지정된 경로 링크
Benjineer 2014

34

활성 레코드의 범위는 클래스 메서드와 비슷하지만 Relation 개체를 반환하므로 다른 범위 또는 활성 레코드 쿼리 메서드를 호출 할 수 있습니다.

예를 들어 아래에 언급 된 범위 방법이있는 Zombie 모델 (zombies 테이블)이있는 경우

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

그리고 당신은 전화

Zombie.rotting.fresh.recent.limit(3)

SQL에서 아래로 번역됩니다.

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

위의 예는 rails 4 구문을 기반으로합니다.


문서에서 order (: created_at, : desc)의 예를 찾을 수 없습니다. 당신이 의미하는 것이 가능 scope :recent, -> { order(created_at: :desc) }합니까? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch

7

세부 사항을 이해하는 가장 좋은 방법은 API 문서로 이동하는 것입니다.

전체 세부 정보와 범위를 사용할 수있는 방법을 얻을 수 있습니다.

범위의 API 문서


7

범위는 클래스 메서드 일뿐입니다.

왜 사용합니까?

범위 지정을 사용하면 연관 개체 또는 모델에 대한 메서드 호출로 참조 할 수있는 일반적으로 사용되는 쿼리 (길거나 가장 자주 사용되는 쿼리의 바로 가기로 간주 될 수 있음)를 지정할 수 있습니다. 이러한 범위를 사용하면 where, joins 및 includes와 같이 이전에 다룬 모든 방법을 사용할 수 있습니다. 모든 범위 메서드는 ActiveRecord :: Relation 개체반환하여 추가 메서드 (예 : 다른 범위)를 호출 할 수 있도록합니다.

간단한 범위를 정의하기 위해 클래스 내에서 범위 메서드를 사용하여이 범위가 호출 될 때 실행할 쿼리를 전달합니다.

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

이것은 클래스 메소드를 정의하는 것과 똑같으며, 사용하는 것은 개인적 선호도의 문제입니다.

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

예제와 함께 전체 설명을 보려면 다음 링크를 따르십시오. 이것이 도움이되기를 바랍니다.

http://guides.rubyonrails.org/active_record_querying.html


3
클래스 메서드를 정의하는 것과 정확히 같지는 않습니다 . 클래스 메서드 nil는 몇 가지 경우에 반환 되므로 특정 조건에 대해 연결할 수 없습니다.
Arslan Ali

1
  • Person 모델이 있다고 상상해보십시오 .

이제 당신을 상상해보십시오.

  • 빨간 머리를 가진 세상의 모든 사람들을 원합니다.
  • 크리켓을하는 세계의 모든 사람들을 원해

범위를 사용하여 특정 클래스의 사람들을 얻을 수 있습니다!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

이제 그렇게 어렵지 않았나요?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.