위임된 유형은 단일 테이블 상속의 대안입니다.
하지만 많은 분들과의 대화에서 들은 바로는,
나는 그들이 제대로 이해되지 않았다고 생각합니다.
특히 나에 의해.
너무 자주 그들은 다형성 협회 주변의 맛으로 언급됩니다.
위임된 유형을 다형성 연결에 대한 편의 메서드로 볼 수 있지만
DHH의 의도는 상당히 달랐습니다.
API는 다형성 연결에 대한 편의상 이치에 맞지 않습니다.
이제 위임된 유형이 무엇을 제공하는지 살펴보겠습니다.
다른 모델과 다형성 연관이 있는 모델이 주어지면,
위임된 유형을 그대로 선언할 수 있습니다.
의도적으로 "오도된"예부터 시작하겠습니다.
class Recommendation < ApplicationRecord
delegated_type :recommendable, types: %w[ Wine Winery ]
end
따라서 와인이나 와이너리에 대한 추천이 될 수 있습니다.
이제 다음과 같은 방법에 액세스할 수 있습니다.
Recommendation.wines # => Recommendation.where(recommendable_type: "Wine")
@recommendation#wine? # => true when recommendable == "Message"
@recommendation#wine # => returns the wine record, when recommendable_type == "Wine", otherwise nil
Recommendation.wineries # => Recommendation.where(entryable_type: "Comment")
좋은 물건.
그러나 이것은 다소 혼란스럽습니다. 한 가지 예를 살펴보겠습니다.
Recommendation.wines
는 무엇을 반환합니까? 메서드가 wines
이므로 와인 레코드를 다시 가져올 것으로 기대합니다. 그러나 그것은 일어나는 일이 아닙니다. 대신 와인에 대한 레코드recommendation
를 얻습니다.나는 이 API가 매우 혼란스럽다는 것을 알았다. 그래서 나는 pull request에서 일부 방법에 별칭을 추가할 것을 제안했습니다.
Recommendation.for_wines
와 같은 호출을 허용하면 이것이 와인 레코드가 아니라 추천 레코드를 반환한다는 것이 더 분명해집니다.그래서 여기서 무슨 일이 일어나고 있습니까? 왜 이렇게 혼란스럽습니까?
종종 이름이 궁금하기도 하고, PR에 대해 다른 사람들과 이야기를 하다 보니 깨달은 것이 있습니다. 위임 유형의 의도를 잘못 이해했습니다.
위임된 유형에 대한 documentation에서 발췌:
You can get around the pagination problem by using single table inheritance, but now you're forced into a single mega table with all the attributes from all subclasses. No matter how divergent. If a Message has a subject, but the comment does not, well, now the comment does anyway! So STI works best when there's little divergence between the subclasses and their attributes.
실제로 전체 문서를 읽으면 다형성 연결에 대한 편의가 아닌 위임된 유형을 완전히 소개합니다. 단일 테이블 상속 또는 다중 테이블에 대한 대안으로 제공됩니다.
따라서 함께 나열/조회하려는 개체가 있는 경우 위임된 유형이 좋은 옵션입니다.
따라서 그런 식으로 보면 API와 이름
DelegatedType
이 훨씬 더 이해되기 시작합니다. Recommendation.wines
는 reccomendations
테이블의 레코드를 반환하지만 이는 와인에 대한 추천이 와인 유형이고 위임된 유형이 와인이라고 잘못 선언했기 때문입니다.좀 더 합리적인 예를 보여주면 훨씬 더 이해가 잘 될 것입니다.
적절한 예
class Product
delegated_type :purchasable, types: %w[Wine Bundle Voucher]
end
와인, 와인 묶음, 바우처를 판매하는 상점을 짓는다고 가정해 보겠습니다. 우리는 실제로 하나의 테이블에서 쿼리하고 페이지를 매길 수 있기를 원하지만 속성 측면에서 매우 다양하므로 STI(단일 테이블 상속)는 훌륭한 솔루션이 아닙니다.
위임된 유형이 들어오는 곳입니다. product_number, 가격, 재고, 게시와 같은 제품 테이블의 공유 속성을 가질 수 있습니다. 그러나 특정 테이블에 필요한 모든 속성을 가질 수도 있습니다. 번들에는 여러 와인이 연결되어 있습니다…
따라서 위임된 유형의 경우
wine
레코드를 products
테이블과 wines
테이블의 "조인된 행"으로 간주합니다.제품
wine
에서 알아야 할 모든 것은 제품 레코드 또는 위임된 유형에서 얻습니다. 따라서 이름은… 실제로 와인 테이블에서만 레코드를 인스턴스화하지 않는 것입니다.class Product < ApplicationRecord
delegated_type :purchasable, types: %w[Wine Bundle Voucher]
delegate :display_name, to: :purchasable
end
class Wine < ApplicationRecord
def display_name
name + vintage
end
end
class Bundle < ApplicationRecord
has_many :wines
def display_name
"#{name} (#{wines.count} wines)"
end
end
class Voucher
def display_name
"#{amount}$ Voucher"
end
end
따라서 제품에 대한 일부 측면과 위임된 유형에 대한 보다 구체적인 측면이 있습니다. OOP 다형성을 활용하고 STI보다 훨씬 더 유연하게 사용할 수 있습니다.
따라서 위임된 유형은 하나의 테이블에 무언가를 저장하고 싶을 때 강력한 도구가 될 수 있으므로 쉽게 쿼리할 수 있고 때로는 더 중요하게는 페이지 매김을 사용할 수 있습니다.
rstuder.ch에 처음 게시됨
Reference
이 문제에 관하여(위임된 유형은 단일 테이블 상속의 대안입니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/rolandstuder/delegated-types-are-an-alternative-to-single-table-inheritance-25k7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)