2010-05-11 1 views
4

두 모델 티켓TicketComment의 TicketComment는 Ticket의 하위 항목입니다.레일은 콜백에 _nested_attributes_을 허용합니다.

ticket.rb

class Ticket < ActiveRecord::Base 
    has_many :ticket_comments, :dependent => :destroy, :order => 'created_at DESC' 

    # allow the ticket comments to be created from within a ticket form 
    accepts_nested_attributes_for :ticket_comments, :reject_if => proc { |attributes| attributes['comment'].blank? } 
end 

ticket_comment.rb

class TicketComment < ActiveRecord::Base 
    belongs_to :ticket 

    validates_presence_of :comment 
end 

내가하고 싶은 것은 어디 경우 Trac에,의 기능을 모방하다 에이 사용자가 티켓을 변경하거나 설명을 추가하면 티켓에 지정된 사람에게 전자 메일이 전송됩니다.

전자 메일을 보내기 전에 정보가 모두 저장되었음을 알 수 있도록 after_update 또는 after_save 콜백을 사용하고 싶습니다.

모델 (ticket.changes)의 변경 사항과 새 메모가 작성되었는지 (ticket.comments),이 업데이트를 보낼지 (x 변경 사항은 y, 사용자는 '텍스트 추가'사용자 의견) 어떻게 감지 할 수 있습니까? 하나의 이메일에 콜백 메소드를 사용 하시겠습니까?

+0

아하, 질문을 잘못 해석 한 것 같습니다. 사과. 나는 실제 해결책을 제시하려고 노력할 것이다. –

답변

4

ActiveRecord::Dirty 모듈을 사용하면 저장되지 않은 변경 사항을 추적 할 수 있습니다.

예.

t1 = Ticket.first 
t1.some_attribute = some_new_value 
t1.changed? => true 
t1.some_attribute_changed? => true 
t1.some_attribute_was => old_value 

before_create의 before_update 안에 있으므로 저장 전에만 확인할 수 있습니다.

이러한 모든 방법을 모으는 아주 좋은 장소는 Observer-class TicketObserver에 있으므로 실제 모델에서 "관찰자"코드를 분리 할 수 ​​있습니다.

예.

class TicketObserver < ActiveRecord::Observer 
    def before_update 
    .. do some checking here .. 
    end 
end 

는 관찰자 클래스를 사용하려면, 당신은 당신의 environment.rb이를 추가해야합니다

config.active_record.observers = :ticket_observer 

이것은 당신이 :)

은 무엇 링크 된 의견에 관한 시작할 수 있습니다. 다음과 같이하면 :

new_comment = ticket.ticket_comments.build 
new_comment.new_record? => true 
ticket.comments.changed => true 

이렇게하면 정확히 무엇이 필요합니다. 그것은 당신을 위해 작동하지 않습니까? 참고 사항 : 다시 저장하기 전에 확인해야합니다.

before_create 또는 before_update에서 변경된 데이터를 수집해야하고 after_update/create에서 실제로 메일을 보내야한다고 생각합니다. 그렇다면 성공했다고 확신합니다.)

분명히 아직 명확하지 않습니다. 나는 그것을 좀더 명백하게 할 것이다. TicketObserver 클래스를 사용하는 것이 좋습니다.그러나 콜백을 사용하려면 다음과 같이하십시오.

class Ticked 

    before_save :check_state 
    after_save :send_mail_if_needed 

    def check_state 
    @logmsg="" 
    if ticket_comments.changed 
     # find the comment 
     ticket_comments.each do |c| 
     @logmsg << "comment changed" if c.changed? 
     @logmsg << "comment added" if c.new_record? 
     end 
    end 
    end 

end 
def send_mail_if_needed 
    if @logmsg.size > 0 
    ..send mail.. 
    end 
end 
+0

이미 더러운 코드가 작동하고 있습니다. 그 부분을 이해합니다. 여기서 어려운 부분은 Child 객체 인 TicketComment가 만들어 졌는지 확인하는 것입니다. 하나가 포함되어 있다면 그 내용을 추가해야합니다. 불행히도 그 아이들은 '변경'배열에 나타나지 않습니다. 더러운 것이 아닙니다. 더러운 것이 아닙니다. – Rabbott

+0

안녕하세요, 그에 따라 답변을 연장했습니다. 지금은 더 이해가 되니? – nathanvda

+0

네, 그 모든 것을 이해합니다 .. 나는 더티를 이해합니다. 더러운 doesnt는 나를 도와 준다. 양식이 제출되면, 컨트롤러에 해시 (params [: ticket])가 있고, 새로운 ticket_comment가 생성되어 해시 내에 제공됩니다. 티켓 오브젝트가 저장됩니다. ticket_comment가 저장됩니다. 이제 콜백에서 나는 SELF가있다. 덧글이 추가되었다는 것을 어떻게 알 수 있는가? 그리고 그 주석을 어떻게 얻을 수 있는가? – Rabbott