2013-03-25 3 views
0

User.rb, Question.rbAnswer.rb 모델이있는 레일스 애플리케이션이 있습니다. 예측 가능한 관계는 각 모델 사이에 정의됩니다. 사용자 has_many 질문, 사용자도 has_many 답변. 질문 has_many도 대답.동시에 두 개의 인스턴스 변수 업데이트하기

나는 질문자에게 대답을 선택할 수있는 옵션을 'best answer'으로 지정하려고합니다. 따라서 Answers 컨트롤러에서 'bestAnswer'컨트롤러 동작을 만들었습니다. 이 컨트롤러 동작에서는 @question에 최상의 답변 ID를 저장하고 특히 @answer이 최선의 답변으로 선택되었음을 나타냅니다. 따라서, 나는 동시에

if @question.update_attributes(:accepted_answer_id => @answer.id) && @answer.update_attributes(:accepted => true) 

전체 방법에서 모두 @question@answer에 대한 update_attributes에 노력했다.

def bestanswer 


    @answer = Answer.find(params[:answer_id]) 
    @question = Question.find(params[:question_id])  
     if @question.update_attributes(:accepted_answer_id => @answer.id) && @answer.update_attributes(:accepted => true) 
      redirect_to @question, notice: 'You have accepted as best answer' 
     else 
      redirect_to @question, notice: 'There was a problem marking this as best answer. Please try again.' 
     end 
end 

이 기능은 작동하지만, Rails가 트랜잭션을 지원한다는 것도 알고 있습니다. 경험이 없으므로 내가 위에서 한 것처럼 일을해야하는지 아니면 거래를하려고하는지 또는 다른 일을해야하는지 잘 모르겠습니다. 내가 거래를해야한다고 생각하면 어떻게 쓰겠습니까? 나는 트랜잭션이 모델에서 수행되어야한다고 생각하기 때문에 약간 혼란스럽고 모델 등에서 인스턴스 변수를 사용하는 것과 모델을 쓰는 것에 대해 확신 할 수 없다.

업데이트. 다음과 같은 방법으로 첫 번째 대답에서 제안을 구현했습니다. 그것은 작동하지만, 그것은 나에게 이상하게 보입니다. OP가 거래를 어떻게 작성해야하는지 묻자, 나는 누군가가 거래를 컨트롤러 액션에 통합하는 방법을 명확히하기를 희망했다.

  if ActiveRecord::Base.transaction do 
         @question.update_attributes! :accepted_answer_id => @answer.id 
         @answer.update_attributes! :accepted => true 
        end 
       redirect_to @question, notice: 'You have accepted as best answer' 
      else 
       redirect_to @question, notice: 'There was a problem marking this as best answer. Please try again.' 
      end 

답변

1

당신은 액티브 뭔가 잘못되면 update_attributes! 버전은 트리거 예외가 발생하는 경우에만 트랜잭션을 롤백 때문에 나는 여기에 !을 사용

ActiveRecord::Base.transaction do 
    @question.update_attributes! :accepted_answer_id => @answer.id 
    @answer.update_attributes! :accepted => true 
end 

할 수 있습니다. 당신이 당신의 질문 모델에 설정된 has_one :accepted_answer 관계가있는 경우

또한, 수동으로 ID를 설정하는 대신

@question.update_attributes! :accepted_answer => @answer 

를 사용해야합니다. 일반적으로 ActiveRecord가 ID를 관리하도록하는 것이 좋습니다.

+0

감사합니다.하지만 좀 더 자세한 정보를 제공해 줄 수 있습니까? 해당 거래를 bestanswer 조치에 직접 반영합니까? 그렇다면 성공적인 저장 또는 실패한 저장을 위해 리디렉션을 작성하려면 어떻게해야합니까? 또한 has_one : accepted_answer에 대한 아이디어가 마음에 들지만 Answer 모델에 더 많은 기능을 추가하여 작동하도록해야합니까? 나는 이미 belongs_to : Answer 모델에 대한 질문을합니다. 도움을 주셔서 감사합니다. 나는 약간의 경험이 없기 때문에 당신이 제공 할 수있는 세부 사항은 인정 될 것입니다. – BrainLikeADullPencil

+0

OP에 대한 업데이트와 같이 트랜잭션이 작동하지만 실제로 구현 한 방식이 이상하게 보입니다. 그게 네가하는 방법이야? 나는 다른 사람들이 코드를 보았을 때만 배울 뿐이고, 전에 사용 된 코드 중 하나를 보지 못했습니다 ... – BrainLikeADullPencil

+0

레일스가 트랜잭션에서'false'를 리턴 할 지 확신하지 못합니다. 그렇다면 아마 변수에 결과를 저장 한 다음 전체 트랜잭션 메서드에서'if'를 사용하는 대신'if'를 사용합니다. 롤백이 발생할 때마다 던져지는'ActiveRecord :: Rollback'에서 구출 할 수 있습니다. 그래서 그 예외를 잡으면 if 문에서'else' 부분을 실행할 수 있습니다. 그렇지 않으면 성공적으로 반환됩니다. –

관련 문제