2013-03-27 2 views
9

컨트롤러에 예제 액션이 있습니다.RAILS 3 - 컨트롤러의 트랜잭션

def some_action 
product = Product.new 
product.name = "namepro" 
    if product.save 
    client.update_attribute(:product_id,product.id) 
    end 
end 

이 코드의 트랜잭션을 추가하는 방법은 무엇입니까? 나는이 예제 코드로 시도 :

def some_action 
**transaction do** 
    product = Product.new 
    product.name = "namepro" 
    if product.save 
    client.update_attribute(:product_create,Time.now) 
    end 
**end** 
end 

그러나이 오류 발생 :

undefined method `transaction' 

내가 컨트롤러에서 트랜잭션을 사용 읽어 나쁜 연습을하지만 이유는 내가 왜 (http://markdaggett.com/blog/2011/12/01/transactions-in-rails/을 모르는)

예제에서 제품이 생성되어 저장되고 클라이언트 업데이트가 실패한 경우 ... Rails가 아무 것도 수행하지 않아야합니다.

감사합니다.

답변

25

정말로 원하는 경우 컨트롤러에서 트랜잭션을 사용할 수 있습니다. 지적하신대로 나쁜 습관이지만, 수행하고 싶다면 transaction do 대신 Product.transaction do으로 전화하십시오. transactionActiveRecord::Base의 클래스 메소드이므로 ActiveRecord 파생 클래스에서 호출해야합니다. 응용 프로그램의 모든 모델 클래스가 수행 할 것입니다 (여러 가지 모델에 대해 서로 다른 데이터베이스에 연결하는 경우 사실이 아닐 수도 있지만 그렇게하지는 않을 것입니다).

MVC 패러다임에 따라 문제를 적절하게 구분하지 않기 때문에 좋지 않은 이유입니다. 컨트롤러가 데이터 지속성 구현에 관심을 가져서는 안됩니다. 더 나은 방법은 Product에 메소드를 추가하는 것입니다. 이 같은 아마 뭔가 : 대신 컨트롤러에 product.save를 호출

def save_and_update_create_time 
    transaction do 
    if save 
     client.update_attribute(:product_create, Time.now) 
    end 
    end 
end 

그런 다음, product.save_and_update_client_create_time를 호출합니다. 해당 방법으로 client을 전달해야 할 수도 있습니다. client의 출처가 명확하지 않습니다. product의 속성 인 경우 위의 메소드가 작동해야합니다.

컨트롤러 데이터가 필요하지 않고 productclient 인 경우 Rails가 더 잘 수행 할 수있는 방법이 있습니다.

after_save :update_client 

private 

def update_client(product) 
    product.client.update_attribute(:product_create, Time.now) 
end 

는 그 다음 Product가 저장 될 때마다이 연결된 클라이언트의 필드가 업데이트됩니다 그럼 그냥 같이 ( Product 클래스에 추가), after_save 콜백을 사용할 수 있습니다. 먼저 client의 존재를 확인하는 코드를 먼저 소개해야합니다.

깨끗한 코드 외에도 콜백 사용의 이점은 전체 콜백 체인이 저장과 함께 단일 트랜잭션에서 실행된다는 것입니다. 트랜잭션을 수동으로 작성할 필요가 없습니다. Rails documentation에서 콜백에 대해 자세히 알아볼 수 있습니다.

+0

Jim, 당신의 설명으로 정말 도와 줘서 고마워! – user1364684

+3

트랜잭션 논리를 모델에 넣으면 트랜잭션이 하나의 모델로 제한되지 않고 별도의 관심 규칙을 위반하지 않을까요? 일반적으로 거래가 여러 모델에 걸쳐 있고 DB 수준에서 반드시 서로 관련이없는 높은 기회가 있습니다. – xSNRG

+1

그래, 내 의견의 특정 측면에 마음이 바뀌었다. 나는 그것을 컨트롤러 밖으로 유지하는 아이디어를 좋아하지만, 다중 모델 상호 작용은 어딘가에 포장되어야합니다.아마도 다른 클래스 일 수도 있지만 상황에 따라 컨트롤러가 결국 올바른 장소 일 수 있습니다. –

관련 문제