연결 가능한 ActiveRecord 객체 반환 선호

7273 단어 webdevrailsruby
ActiveRecord의 가장 좋은 부분 중 하나는 연결 가능한 쿼리 인터페이스입니다.

Post.includes(:comments)
  .where(published: true)
  .where(author: Current.user)
  .order(:name)


이 강점을 활용하고 코드에 유연성을 제공하려면 데이터를 쿼리할 때 항상 연결 가능한 개체를 반환하도록 하세요.

용법



애플리케이션이 커짐에 따라 복잡한 쿼리를 추출하는 것이 일반적입니다.

class SpecialOffer

  def self.find_eligible_products(store, shopper)
    return [] if store.restricted?

    store.products
      .where('price >= ?', 100)
      .select{ |p| shopper.can_order?(p) }
  end
end

@products = SpecialOffer.find_eligible_products(store, shopper)
#=> [#<Product:0x00007fb1719b7ec0>, #<Product:0x00007fb174744de8>, ...]


이 코드는 작동할 수 있지만 특정 방식으로 @products를 주문해야 하는 경우 어떻게 됩니까? 아니면 추가 로직을 추가하시겠습니까? 아니면 일부 연결을 지연 로드하시겠습니까?

이 경우 SpecialOffer 메서드의 반환 유형은 배열입니다. sortselect와 같은 Ruby 배열 방법을 사용하도록 전환해야 하며 더 많은 데이터가 필요한 경우 실수로 N+1 버그를 도입할 수 있습니다.

이 코드를 리팩토링하여 연결 가능한 객체를 반환하도록 합시다.

class SpecialOffer

  def self.find_eligible_products(store, shopper)
    return Product.none if store.restricted?

    product_ids = store.products
      .where('price >= ?', 100)
      .select{ |p| shopper.can_order?(p) }
      .map(&:id)

    Product.where(id: product_ids)
  end
end

@products = SpecialOffer.find_eligible_products(store, shopper)
#=> Product::ActiveRecord_Relation


먼저 none 쿼리 메서드를 사용합니다. 이 메서드는 비어 있지만 여전히 연결 가능한 결과를 반환합니다. 이 빈 관계에서 order , includes 또는 where 와 같은 ActiveRecord 메서드를 호출할 수 있으며 단순히 결과를 반환하지 않습니다.

둘째, 복잡한 제품 쿼리의 결과를 직접 반환하는 대신 올바른 제품을 수집한 다음 해당 제품id에 대해서만 "신선한"결과를 반환합니다. 이로 인해 추가 데이터베이스 쿼리가 발생하지만 필요에 따라 결과를 조작할 수도 있습니다.

결과를 정렬하거나 연결을 로드하려는 경우 데이터베이스에서 수행할 수 있으며 계산의 일부로 실행된 기존 조건에 대해 걱정할 필요가 없습니다.

@products = SpecialOffer.find_eligible_products(store, shopper)
  .includes(:variants)
  .order(:price)

@products = SpecialOffer.find_eligible_products(store, shopper)
  .joins(:sales)
  .where("sales.count > 15")
  .order(:sku)


저는 이 패턴이 데이터를 올바른 모양으로 마사지하는 유연성을 유지하면서 복잡한 쿼리를 추출하는 데 매우 유용하다는 것을 알았습니다.

추가 리소스



레일스 API: ActiveRecord::QueryMethods#none

레일스 문서: Active Record Query Interface

좋은 웹페이지 즐겨찾기