2012-07-09 3 views
2

STI 유형을 통해 특정 클래스의 모델을 대상으로하는 범위에서 build 메서드를 호출하고 ActiveRecord에서 올바른 클래스.ActiveRecord는 STI 클래스를 대상으로하는 범위를 통해 잘못된 클래스의 인스턴스를 만듭니다.

class LineItem < ActiveRecord::Base 
    scope :discount, where(type: 'DiscountLineItem') 
end 

class DiscountLineItem < LineItem; end 

> LineItem.discount.build # Expect an instance of DiscountLineItem here 
=> #<LineItem ...> 

자, 내가 DiscountLineItem의 인스턴스 LineItem 아닌 인스턴스를 기대했다.

답변

4

ActiveRecord가 올바른 클래스로 개체를 인스턴스화하지는 않지만 형식을 올바르게 설정합니다.

1) 객체를 생성 한 후 데이터베이스에서 다시로드 : 그것에서 직접 객체를

item = LineItem.discount.create(attrs...) 
item = LineItem.find(item.id) 

2) STI 클래스를 사용하여 구축 :

DiscountLineItem.build 
당신은 기본적으로이 약 2 가지 방법이 있습니다

ActiveRecord가 할 수있는 모든 것들을 감안할 때 이것은 무의미한 제한 사항처럼 보이고 변경하기가 그리 어렵지 않을 수 있습니다. 이제 당신은 감정을 상하게 한 내 관심 :)

업데이트 :

당신이 BaseClass.new (수행 할 수 있습니다 :

이 커밋 다음과 같은 메시지가 최근 added to Rails 4.0이었다 유형 => " SubClass "), parent.children.build (: type =>"SubClass ") 또는 parent.build_child to STI 하위 클래스를 초기화하십시오. 클래스 이름이 유효한 클래스이고, 연관이 기대하는 수퍼 클래스의 조상에 있음을 보장합니다.

+0

아마도이 토론을 레일스 트래커로 옮길 때입니다. 나는 실패한 테스트 케이스를 작성하고 오늘 게시 할 것이다. – steveluscher

+0

지난 밤에 수정 사항을 코딩하여 피드백을 위해 레일 핵심 Google 그룹에 게시 할 예정이었습니다. 내가 기회를 얻을 때 나는 업데이트로 여기에 나중에 저녁을 게시 할 수 있습니다. –

+0

@steveluscher 여기 당신이 시도 할 수 있습니다 액티브에 대한 패치입니다 : https://gist.github.com/5cad22a11f011052d8f6 –

1

build을 잊어 버리십시오. 일부 LineIteml이 있고이 경우 l.discount 당신은 LineItem 경우,하지 DiscountLineItem 인스턴스를받을거야. 당신이 DiscountLineItem 인스턴스를 얻고 싶은 경우에, 나는 이제 DiscountLineItem 인스턴스의 컬렉션을 다시 얻을 것이다 방법

def self.discount 
    where(type: 'DiscountLineItem').map { |l| l.becomes(l.type.constantize) } 
end 

로 범위를 변환하는 것이 좋습니다.

+0

그건'def self.discount'이어야합니다. –

+1

저는 개념을 좋아하지만 맵을 사용하면 ActiveRecord :: Relation 객체를 배열로 변환하기 때문에 다른 범위 나 메서드를 연결할 수있는 능력이 사라집니다. 이것을 올바르게 수행 할 수있는 방법이 있어야합니다./ –

+0

그래, 그냥 다시 관계로 변환하는 문서를 읽을 필요가있다. – deefour

관련 문제