2011-02-10 2 views
1

나는 하나의 테이블 상속을 사용하고 다른 유형 (학년 또는 학년 유형의 학년)이있는 모델을 가지고 있으며 각 유형마다 고유 한 유효성 검사가 있습니다. 사용자가 레코드 유형을 변경하려고 시도하면 드롭 다운에서 어떤 학년 유형을 선택하고 변경할 수 있습니다. 그러나 사용자가 유형을 변경하면 새 클래스 유효성 검사를 실행하는 방법과 오래된 유효성 검사를 수행하는 방법을 파악할 수 없습니다. 올해의 유형 학기, 그리고 사용자가 분기로 변경하는 경우 레코드 유형을 변경하고 유형 열을 사용하여 올바른 클래스의 유효성 검사를 레일에서 실행하는 방법은 무엇입니까?

@school_year = SchoolYear.find(params[:id]) 
respond_to do |format| 
    if SchoolYear::SUBCLASSES.include? params[:school_year]['type'] 
    @school_year[:type] = params[:school_year]['type'] 
    else 
    raise "Invalid type" 
    end 

    if @school_year.update_attributes(params[:school_year]) 
    # done 
    else 
    # validation problem? 
    end 

지금, 내가 QuarterSchoolYear의 검증이 아니라 학기 사람들의 실행 것으로 예상 다음과 같이 예를 들어, 내 코드입니다. 어떻게 작동하도록 코드를 변경합니까?

답변

3

유형을 변경 한 후에 개체를 다시로드해야합니다. 'type'속성에 새 값을 할당해도 객체의 루비 클래스는 변경되지 않습니다. 물론, 타입 변경 직후에 객체를 저장하면 오래된 검증이 사용됩니다.

데이터베이스의 형식 특성을 업데이트 한 다음 개체를로드하려고 할 수 있습니다. 같은 뭔가 :

[..] 
if type_differs_and_is_acceptable_to_change 
    SchoolYear.update_all(
    ['type = ?', params[:shool_year][:type] ], 
    ['id = ?',@school_year.id ] 
) 
    @school_year = SchoolYear.find(@school_year.id) 
end 
if @school_year.update_attributes... 

가지고해야합니다 :이 클래스 attr_accessible에 NOT 입력합니다.

그 외에도 개체의 유형을 변경하는 것이 약간 불안하지만 개인적인 두려움 일 수 있습니다. :)

1

유효성 검사를 실행하려면 올바른 유형의 모델로 인스턴스화해야합니다.

new_type = params[:school_year]['type'] 
@school_year[:type] = new_type 
@school_year.save! 
@school_year = new_type.constantize.find(@school_year.id) 
@school_year.update_attributes(params[:school_year]) 

당신은 아마 update_attributes을 경우 유형의 변화를 롤백 할 수 있도록 트랜잭션에 넣고 싶어 : 나는 새로운 형태로 저장하고 다시 찾을 수를 제외 할 수있는 방법이 표시되지 않습니다 실패합니다.

+0

트랜잭션에서 실제 저장하지 않으므로 찾기에 실패하므로 ur 코드의 4 행에서 실패합니다. – umar

+0

"실제로 거래에서 저장하지 않는다"는 것은 무엇을 의미합니까? 'save! '가 예외를 발생 시키는가? – zetetic

+0

내 말은 트랜잭션에 둘 이상의 "저장"을 넣고 트랜잭션 내에서 충돌을 일으키지 않으면 모두 기록된다는 것입니다. 따라서 트랜잭션 중에 "저장"을 작성하여 찾으면 실제로 쓰여지지 않았으므로 메모리에서 제외하고 찾을 수 없습니다. 액세스 할 수있는 방법은 없습니다. 그래서 행은 실제로 3 행에서 변경되지 않았으므로, 4 행의 ur 코드에서 찾기가 실패합니다. 그래서이 방법은 효과가 없습니다. – umar

3

이것은 오래되었지만 @ Arsen7의 제안에 따라 개선되고 개선되었습니다. 개체를 새로운 유형으로 다시로드하는 가장 좋은 방법은 다음과 같은 ActiveRecord 방법을 사용하는 것이고, 유형을 변경 한 후에 객체를 저장해야합니다. 이렇게하면 데이터베이스에 두 번 도달하지 않습니다.

[..] 
if type_differs_and_is_acceptable_to_change 
    @school_year.type = params[:school_year][:type] 
    @school_year = @school_year.becomes(@school_year.type.constantize) 
end 
if @school_year.update_attributes... 
+1

이것은 완벽하게 작동합니다. 유형을 변경하고 유효성 검사를 저장시 실행할 수 있습니다! –

관련 문제