2009-08-19 61 views
0

我有一個ImagesController,它啓動了一個非平凡的保存操作。這裏的高級背景:強制保存!操作失敗

我有幾種不同的物理文件類型來處理我的應用程序。這些每個belongs_to a Binary。當然,可以創建文件,並且此過程涉及將物理文件上傳到臨時位置,可能驗證物理文件(對於大小,類型或其他),然後假設沒有問題將文件移動到永久位置然後在適當的表格中創建數據庫記錄(爲了我的問題,我們使用imagesbinaries)。

Image屬於Binary並且有BinaryObserver觀察Image類。在那個觀察者類中,有一個before_create()方法,它告訴Binary類上傳圖像的物理文件並在數據庫中保存相關記錄(包括名稱,路徑,URI信息等)。

觀察者類方法所做的一件事是測試原始模型中的回調方法,在這種情況下爲Image。如果方法存在並因任何原因返回false,那麼我需要保存操作失敗。我無法弄清楚如何做到這一點。

在我的控制器的create()方法,我有:

if @image.save! 
    flash[:notice] = "Successfully created image." 
    redirect_to @image 
else 
    flash[:notice] = "Upload failed." 
    render :action => 'new' 
end 

我無法弄清楚如何觸發else塊。在我BinaryObserver類,我有:

def before_create(model) 
    binary = Binary.new.upload(model.upload) 

    if !model.respond_to?('before_file_save') || model.before_file_save() 
     binary   = binary.store() 
     model.binary_id = binary.id 
     model.active = 1 

     return true 
    else 
     # binary.destroy() 
     File.delete(File.join(Rails.root, binary.path)) 
     return false 
    end 
end 

目前,Image.before_file_save()僅返回false。物理文件被刪除,但保存並未失敗,並且我的控制器顯示一條錯誤消息,表明其show()方法找不到圖像(這是合理的,因爲圖像未保存且物理文件已被刪除)。

如果觀察者類'before_create()方法返回false,我該如何強制保存操作失敗?

謝謝。

回答

1

這是我的理解是,如果操作失敗,在Model方法上使用bang(!)語法將引發異常。顯然,保存並不失敗,但Observer需要讓你的控制器知道出了問題。我會按照這樣做的相同AR的方式,有例外:

begin 
    @image.save! 
    flash[:notice] = "Successfully created image." 
    redirect_to @image 
rescue YourObserverException => e 
    flash[:notice] = "Upload failed." 
    render :action => 'new' 
end 

這意味着觀察者沒有返回true,但如果上傳失敗確實引起YourObserverException(你在哪裏returning false)。

+1

我更喜歡你的方法 - 更清潔。 – 2009-08-19 23:44:52

+0

謝謝,這個工作很好,一旦我想出瞭如何在Ruby中引發異常。我通常是異常處理的重要用戶,但我想我只是假定返回false會使保存無效。科迪上面說的是合理的,但是模型完整性仍然完好無損,因爲這是在保存之前發生的。 – 2009-08-20 00:15:42

0

您的觀察者IS仍在基本上位於頂部的ActiveRecord Transaction內部運行。所以DB明智的你應該仍然有誠信。但是爲了將這些信息傳遞給頂端,我會在返回false之前在對象中設置一個實例變量。由於控制器仍然在Observer的同一個對象上運行,因此可以使用相同的信息。

...在你的觀察 model.is_valid =假#or_something_went_wrong =真等 返回false

然後,只需對相應的操作在您的控制器。