상속
개요
Mongoid는 최상위 문서와 내장된 문서 모두에서 상속을 지원합니다. 하위 문서가 상위 문서에서 상속되면 상위 문서의 필드, 연결, 검증 및 범위가 하위 문서에 복사됩니다.
class Canvas include Mongoid::Document field :name, type: String embeds_many :shapes end class Browser < Canvas field :version, type: Integer scope :recent, ->{ where(:version.gt => 3) } end class Firefox < Browser end class Shape include Mongoid::Document field :x, type: Integer field :y, type: Integer embedded_in :canvas end class Circle < Shape field :radius, type: Float end class Rectangle < Shape field :width, type: Float field :height, type: Float end
위의 예에서 Canvas
, Browser
및 Firefox
는 모두 캔버스 컬렉션에 저장됩니다. 데이터베이스에서 로드할 때 올바른 문서가 반환되는지 확인하기 위해 추가 속성 _type
이 저장됩니다. 이는 내장된 문서 Circle
, Rectangle
및 Shape
에도 적용됩니다.
참고
Circle
을 검색할 때 쿼리는 _type
(또는 판별자 키가 설정된 값) 필드에 Circle
(또는 판별자 값이 설정된 값)이 있는 모양 컬렉션의 문서만 반환하고, 다른 모든 판별자 값은 모양 클래스의 객체로 간주합니다.
마찬가지로 상위 클래스(이 예에서는 Canvas
)로 쿼리할 때 컬렉션에서 판별자 값이 없거나 판별자 값이 상위 또는 그 하위 항목에 매핑되지 않는 모든 문서는 상위 클래스의 인스턴스로 반환됩니다.
판별자 키 변경
Mongoid는 기본 _type
에서 판별자 키 변경을 지원합니다. 이 작업을 수행해야 하는 경우가 몇 가지 있습니다:
최적화하려는 경우:
_t
와 같이 더 짧은 키를 사용할 것을 권장합니다.기존 시스템으로 작업하려는 경우: 사용자가 사전 정의된 키가 있는 기존 시스템 또는 데이터세트로 작업하고 있을 수 있습니다.
판별자 키를 변경하는 방법에는 클래스 수준과 전역 수준, 이렇게 두 가지가 있습니다. 클래스 수준에서 판별자 키를 변경하려면 discriminator_key=
메서드를 사용하여 상위 클래스에서 직접 판별자 키를 설정할 수 있습니다. 위의 예를 들어 보겠습니다:
class Shape include Mongoid::Document field :x, type: Integer field :y, type: Integer embedded_in :canvas self.discriminator_key = "shape_type" end class Circle < Shape field :radius, type: Float end class Rectangle < Shape field :width, type: Float field :height, type: Float end
여기서는 discriminator_key=
setter에 대한 호출이 상위 클래스에 추가되었습니다. 이제 Rectangle 또는 Circle을 만들 때 shape_type
필드가 추가됩니다.
판별자 키는 상위 클래스에서만 수정할 수 있으며 하위 클래스에 설정하려고 하면 오류가 발생합니다.
하위 클래스를 만든 후 판별자 키를 변경하면 새 판별자 키 값과 함께 새 필드가 추가되고 이전 필드는 변경되지 않습니다. 예시:
class Shape include Mongoid::Document field :x, type: Integer field :y, type: Integer embedded_in :canvas end class Circle < Shape field :radius, type: Float end class Rectangle < Shape field :width, type: Float field :height, type: Float end Shape.discriminator_key = "shape_type"
이 경우 Rectangle 또는 Circle을 만들 때 각각 Rectangle
또는 Circle
로 기본 설정된 shape_type
및 _type
필드가 둘 다 포함됩니다.
판별자 키는 전역 수준에서도 설정할 수 있습니다. 즉, 모든 클래스가 _type
대신 전역으로 설정된 판별자 키를 사용하게 됩니다. 위의 예를 들어 보겠습니다:
Mongoid.discriminator_key = "_the_type" class Shape include Mongoid::Document field :x, type: Integer field :y, type: Integer embedded_in :canvas end class Circle < Shape field :radius, type: Float end class Rectangle < Shape field :width, type: Float field :height, type: Float end
전역 판별자 키를 설정한 후 모든 클래스는 _the_type
을 판별자 키로 사용하며 _type
필드를 포함하지 않습니다.
전역 수준에서 판별자 키를 정의할 때 하위 클래스가 해당 전역 값을 사용하려면 하위 클래스를 정의하기 전에 먼저 설정해야 합니다. 그러나 전역 수준에서 사용자가 하위 클래스를 정의하기 전에 판별자 키를 설정하지 않으면 판별자 필드에 해당 하위 클래스의 새 전역 설정이 아닌 기본값 _type
이 사용됩니다.
판별자 값 변경
Mongoid는 클래스 이름인 기본값에서 판별자 값을 변경하는 것도 지원합니다. 특정 클래스에서 discriminator_value=
메서드를 사용하여 판별자 값을 변경할 수 있습니다.
위의 예를 들어 보겠습니다:
class Shape include Mongoid::Document field :x, type: Integer field :y, type: Integer embedded_in :canvas end class Circle < Shape field :radius, type: Float self.discriminator_value = "round thing" end class Rectangle < Shape field :width, type: Float field :height, type: Float end
여기서는 discriminator_value=
setter에 대한 호출이 Circle
에 추가되었습니다. 이제 Circle
생성 시 문서에는 키 _type
(또는 discriminator_key
가 변경된 항목) 및 값 '둥근 물체(round thing)'가 포함된 필드가 포함됩니다.
참고
판별자 값 재정의는 하위 클래스에서 선언되므로 쿼리에서 찾을 가능성이 있는 하위 클래스를 해당 쿼리를 전송하기 전에 먼저 로드해야 합니다. 위의 예에서 반환된 문서가 잠재적으로 Circle
인스턴스일 수 있는 경우 Shape
에서 쿼리할 때 Circle
클래스 정의를 로드해야 합니다(자동 로드는 "round thing"
에서 Circle
로 해석되지 않기 때문).
서브클래스 쿼리
하위 클래스에 대한 쿼리는 일반적인 방식으로 처리되며, 문서가 모두 동일한 컬렉션에 있더라도 ActiveRecord의 단일 테이블 상속과 마찬가지로 쿼리는 올바른 유형의 문서만 반환합니다.
# Returns Canvas documents and subclasses Canvas.where(name: "Paper") # Returns only Firefox documents Firefox.where(name: "Window 1")
연관 관계
연결의 일반 설정이나 빌드 및 생성 메서드를 통해 has one 또는 has many 연결에 모든 유형의 하위 클래스를 추가할 수 있습니다.
firefox = Firefox.new # Builds a Shape object firefox.shapes.build({ x: 0, y: 0 }) # Builds a Circle object firefox.shapes.build({ x: 0, y: 0 }, Circle) # Creates a Rectangle object firefox.shapes.create({ x: 0, y: 0 }, Rectangle) rect = Rectangle.new(width: 100, height: 200) firefox.shapes
지속성 컨텍스트
Mongoid를 사용하면 하위 클래스의 지속성 컨텍스트를 상위 클래스의 지속성 컨텍스트에서 변경할 수 있습니다. 즉, store_in
메서드를 사용하면 하위 클래스의 문서를 상위 클래스가 아닌 다른 컬렉션(다른 데이터베이스, 클라이언트)에 저장할 수 있습니다.
class Shape include Mongoid::Document store_in collection: :shapes end class Circle < Shape store_in collection: :circles end class Square < Shape store_in collection: :squares end Shape.create! Circle.create! Square.create!
하위 항목에 컬렉션을 설정하면 해당 하위 항목의 문서가 상위 항목의 컬렉션이 아닌 설정된 컬렉션에 저장됩니다.
> db.shapes.find() { "_id" : ObjectId("62fe9a493282a43d6b725e10"), "_type" : "Shape" } > db.circles.find() { "_id" : ObjectId("62fe9a493282a43d6b725e11"), "_type" : "Circle" } > db.squares.find() { "_id" : ObjectId("62fe9a493282a43d6b725e12"), "_type" : "Square" }
컬렉션이 일부 하위 클래스에는 설정되어 있고 다른 하위 클래스에는 설정되어 있지 않은 경우, 컬렉션이 설정된 하위 클래스는 해당 컬렉션에 문서를 저장하고 컬렉션이 설정되어 있지 않은 하위 클래스는 상위 컬렉션에 문서를 저장하게 됩니다.
참고
하위 클래스가 저장된 컬렉션을 변경하면 해당 하위 클래스의 문서가 상위 클래스를 쿼리한 결과에 더 이상 포함되지 않을 수 있습니다.