2012-11-20 4 views
3

레일스 앱에서 한 번에 변경 사항을 일괄 처리하여 각 개별 단계가 아니라 변경 사항의 최종 결과 만 유효성을 검사 할 수 있습니까?업데이트 일괄 확인

약간 애매한 질문 이었으므로 구체적으로 설명하겠습니다.

class Store < ActiveRecord::Base 
    has_many :fruits 
end 

class Fruit < ActiveRecord::Base 
    belongs_to :store 
    attr_accessible :kind, :number, :price 
    validates_uniqueness_of :kind, :scope => :store_id 
end 

나는 다음과 같은 데이터를 데이터베이스 시드했습니다 :

fruits: 
store_id | kind | number | price 
---------------------------------------- 
     1 | apple  |  10 | 0.15 
     1 | banana  |  80 | 0.02 
     1 | cherry  |  25 | 0.50 

을하지만 내가 엉망했습니다 실현, 그리고 바나나의 수와 가격을 교환 나는 식료품의 스토어 앱 있다고 가정 및 버찌. 나는이 작업을 수행 할 수 없습니다

store = Store.find(1) 
old_bananas = store.fruits.where("kind = banana").first 
old_cherries = store.fruits.where("kind = cherry").first 
old_bananas.kind = "cherry" 
old_cherries.kind = "banana" 
old_bananas.save! # => Validation Error 
old_cherries.save! 

는 초를 저장 한 후 괜찮을 했음에도 불구하고, 첫 번째 행을 저장할 때 고유성 제약 조건을 위반되기 때문이다. 두 저장을 함께 배치 할 수 있으며 모든 변경을 한 번에 한 결과 만 볼 수 있습니까?

(내가 해결 생각할 수있는 - 나는 검증 :allow_nil 한 경우, 다음 중 하나를 변경하기 전에 각 행을 nil을, 예를 들면 -하지만 "적절한"솔루션이있는 경우 내가 알고 싶습니다)

답변

1

제약 조건이 유효성 검사 일뿐 데이터베이스에서 적용되는 고유 인덱스가없는 경우 update_attribute 메서드를 사용합니다. 유효성 검사를 건너 뜁니다.

store.fruits.where("kind = banana").first.update_attribute(:kind, "cherry") 
store.fruits.where("kind = cherry").first.update_attribute(:kind, "banana") 

또는 단순히 save(validate: false) 대신 save! 사용합니다.

편집 : 당신은 고유 인덱스를 가지고 있기 때문에, 죽은 간단한 해결책이 임시 값 사용하는 것입니다

store.fruits.where("kind = banana").first.update_attribute(:kind, "foo") 
store.fruits.where("kind = cherry").first.update_attribute(:kind, "banana") 
store.fruits.where("kind = foo" ).first.update_attribute(:kind, "cherry") 

내가 SQL에 자리에서 행 사이의 값을 교환 할 수있는 방법을 알고 아니에요을, 이것은 모델 레벨 검증이 쉽게 우회 될 수 있기 때문에 실제로 여기서 문제입니다.

+0

슬프게도 나는 [[ "store_id", "kind"]에 고유 색인을 가지고 있습니다. 아마 그것을 제거하도록 설득 될 수 있지만, 또 다른 해결책이 있습니까? 이것은 테스트 프레임 워크에서 진행되므로 약간 더러운 속임수를 공개합니다. 예를 들어 원시 SQL로 할 수 있습니까? – Chowlett