Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

범위 또는 클래스 메서드를 사용해야 합니까?

홍순상 덕분에 이 기사는 한국어로도 볼 수 있습니다!

범위는 데이터베이스에서 올바른 개체를 가져오는 좋은 방법입니다.

앱/모델/리뷰.rb
class Review < ActiveRecord::Base
  scope :most_recent, -> (limit) { order("created_at desc").limit(limit) }
end

다음과 같이 범위를 사용합니다.

앱/모델/홈페이지_컨트롤러.rb
@recent_reviews = Review.most_recent(5)

하지만 그 범위를 호출하면 정확하게 보입니다. Review에서 클래스 메서드를 호출하는 것과 같습니다. . 대신 클래스 메서드로 빌드하기 쉽습니다.

앱/모델/리뷰.rb
def self.most_recent(limit)
  order("created_at desc").limit(limit)
end
앱/컨트롤러/홈페이지_컨트롤러.rb
@recent_reviews = Review.most_recent(5)

그러면 일반 Ruby 클래스 메서드를 사용할 수 있는데도 범위를 사용하는 이유는 무엇입니까? 이것들을 완전히 별개이지만 동등한 개념으로 머리 속에 간직할 가치가 있습니까? 이상한 버그를 만난다면? 이 모든 추가 요소가 Rails를 배우기 어렵게 만드는 종류가 아닌가요?

언제 클래스 메서드 대신 범위를 사용하는 것이 합리적입니까?

이미 클래스 메서드가 있는데 범위를 사용하는 이유는 무엇입니까?

특정 날짜 이후에 작성된 모든 리뷰를 가져오고 싶다면 어떻게 하시겠습니까? 그러나 날짜가 지정되지 않은 경우 모두 리뷰가 대신 반환되었습니까?

범위는 다음과 같습니다.

앱/모델/리뷰.rb
scope :created_since, ->(time) { where("reviews.created_at > ?", time) if time.present? }

충분히 쉽죠? 수업 방식은 어떻습니까?

앱/모델/리뷰.rb
def self.created_since(time)
  if time.present?
    where("reviews.created_at > ?", time)
  else
    all
  end
end

약간의 추가 작업이 필요합니다. 범위는 범위를 반환하는 것을 선호하므로 함께 연결하기 쉽습니다.

Review.positive.created_since(5.days.ago)

하지만 클래스 메서드가 같은 방식으로 작동하도록 하려면 시간이 0인 경우를 구체적으로 처리해야 합니다. 그렇지 않으면 발신자 유효하고 연결 가능한 범위가 있는지 파악해야 합니다.

항상 같은 종류의 객체를 반환하는 메서드는 정말 유용합니다. . 극단적인 경우나 오류에 대해 많이 걱정할 필요가 없습니다. 항상 사용할 수 있는 물건을 돌려받는다고 가정할 수 있습니다.

여기에서 nil에 대해 걱정할 필요 없이 범위를 함께 연결할 수 있음을 의미합니다. 값이 돌아옵니다.

항상 범위를 되찾을 것이라는 가정을 깨는 방법이 여전히 있습니다.

앱/모델/리뷰.rb
scope :broken, -> { "Hello!!!" }
irb(main):001:0> Review.broken.most_recent(5)
NoMethodError: undefined method `most_recent' for "Hello!!!":String

하지만 실제 코드에서는 그런 일이 발생하지 않았습니다.

스코프에서 가장 마음에 드는 점은 의도를 표현한다는 것입니다. . 코드를 읽는 다음 사람에게 "이 방법은 연결될 수 있고 결국에는 개체 목록으로 바뀌며 올바른 개체 집합을 선택하는 데 도움이 될 것입니다."라고 말하고 있습니다. 이는 일반적인 클래스 메서드가 말하는 것보다 훨씬 더 많습니다.

범위 대신 클래스 메서드를 사용해야 하는 경우

범위는 의도를 표현하기 때문에 간단한 기본 제공 범위(예:wherelimit ) 더 복잡한 범위로 . 적절한 개체 묶음을 찾는 것이 스코프가 설계된 목적입니다.

두 가지 예외가 있습니다:

  1. 범위를 미리 로드해야 할 때 대신 연결로 전환합니다. .
  2. 기본 제공 범위를 더 큰 범위로 연결하는 것 이상을 수행할 때 클래스 메서드를 사용합니다. .

범위 논리가 복잡해지면 클래스 메서드가 적절한 위치에 있는 것처럼 느껴집니다.

클래스 메서드 내에서 Ruby 코드와 데이터베이스 코드를 쉽게 혼합할 수 있습니다. Ruby에서 작성하기 더 쉬운 정렬 코드가 있는 경우 기본 순서로 개체를 가져오고 sort_by를 사용하여 올바른 순서로 배치할 수 있습니다.

또는 특별히 까다롭다고 느끼면 클래스 메서드가 데이터베이스, Redis, 외부 API 또는 서비스와 같은 몇 가지 다른 위치에서 데이터를 가져올 수 있습니다. 그런 다음 모든 것을 느끼는 개체 모음으로 조합할 수 있습니다. 배열로 변한 범위와 같습니다.

그렇더라도 선택, 정렬, 결합 및 필터링 코드를 범위 안에 넣는 것은 여전히 ​​좋습니다. 그런 다음 클래스 메서드 내에서 범위를 사용합니다. 앱 전체에서 사용할 수 있는 보다 명확한 클래스 메서드와 범위를 갖게 됩니다.

스코프는 제가 가장 좋아하는 Rails 기능 중 하나입니다. 몇 가지 강력한 작업을 수행할 수 있습니다. 특히 유용한 범위 예제를 보려면 Rails 모델 정렬 및 필터링에 대한 제 기사를 읽어보세요.

스코프 사용을 마스터하는 정말 간단한 방법이 있습니다. 작고 집중된 앱에서 스코프를 사용하는 것입니다. Rracticing Rails의 무료 샘플 장에서 방법을 보여줍니다. 확인해 보세요!