2011-05-16 45 views
5

我在我的Rails 3示例應用程序上使用CarrierWave。我想,當用戶提交一個無效的URL空的,或者不是圖像來驗證遠程位置上傳,所以我沒有得到標準錯誤異常:我該怎麼做:使用CarrierWave進行遠程位置驗證?

CarrierWave::DownloadError in ImageController#create 
trying to download a file which is not served over HTTP 

這是我的模型:

class Painting < ActiveRecord::Base 
    attr_accessible :gallery_id, :name, :image, :remote_image_url 
    belongs_to :gallery 
    mount_uploader :image, ImageUploader 

    validates :name,  :presence => true, 
          :length => { :minimum => 5, :maximum => 100 } 
    validates :image,  :presence => true 

end 

這是我的控制器:

class PaintingsController < ApplicationController 
    def new 
    @painting = Painting.new(:gallery_id => params[:gallery_id]) 
    end 

    def create 
    @painting = Painting.new(params[:painting]) 
    if @painting.save 
     flash[:notice] = "Successfully created painting." 
     redirect_to @painting.gallery 
    else 
     render :action => 'new' 
    end 
    end 

    def edit 
    @painting = Painting.find(params[:id]) 
    end 

    def update 
    @painting = Painting.find(params[:id]) 
    if @painting.update_attributes(params[:painting]) 
     flash[:notice] = "Successfully updated painting." 
     redirect_to @painting.gallery 
    else 
     render :action => 'edit' 
    end 
    end 

    def destroy 
    @painting = Painting.find(params[:id]) 
    @painting.destroy 
    flash[:notice] = "Successfully destroyed painting." 
    redirect_to @painting.gallery 
    end 
end 

我真的不知道該如何處理這個問題,所以任何見解將是巨大的。

+1

我不確定是否最好的方法去創建:在模型中驗證:remote_image_url,並有一個正則表達式來驗證它是否是一個URL和圖像。 – 2011-05-16 02:28:51

回答

0

此問題的解決方案已添加到Github上的CarrierWave Wiki

編輯:
我想現在落實提出的解決方案,但我不能得到它的工作。我正在使用AR on Rails 3.1.3。

在維基上實現代碼的方式導致驗證實際上正常發生。當我嘗試上傳亂碼時,我收到了一個很好的驗證信息。問題是,正常上傳也被阻止。

+0

此解決方案不適用於mongoid。如果任何與mongoid工作可以檢查它plase – hyperrjas 2011-12-20 19:20:57

8

我遇到了同樣的問題。不幸的是,它看起來像是CarrierWave的一個設計缺陷......它不允許正確驗證遠程URL。 當屬性設置時,CarrierWave將立即嘗試下載資源,並且如果URL無效,無法訪問或資源不具有預期類型,則會引發異常。 在發生任何驗證之前,總會拋出DownloadError或IntegrityErrors。

因此我無法找到使用其他驗證程序的良好解決方法。我的解決方案最終看上去像這樣:

valid = false 
begin 
    par = params[:image].except(:remote_upload_url) 
    @image = Image.new(par) 
    # this may fail: 
    @image.remote_upload_url = params[:image][:remote_upload_url] 
    valid = true 
rescue CarrierWave::DownloadError 
    @image.errors.add(:remote_upload_url, "This url doesn't appear to be valid") 
rescue CarrierWave::IntegrityError 
    @image.errors.add(:remote_upload_url, "This url does not appear to point to a valid image") 
end 

# validate and save if no exceptions were thrown above 
if valid && @image.save 
    redirect_to(images_configure_path) 
else 
render :action => 'new' 
end 

基本上,我在包裝救援塊構造和最初設定的所有參數除了遠程URL。當我設置它時,可能會發生異常,我通過手動設置模型中的錯誤來處理。請注意,在這種情況下不會執行其他驗證。這是一個黑客,但爲我工作。

我希望這可以通過推遲下載資源直到模型驗證階段或之後在未來的版本中解決。

1

這是非常討厭的問題。我現在在我的application_controller.rb中執行了rescue_from,只是閃現的消息指出了這個問題。這是關於我能想到的最好的。如果你有多個需要這些驗證的模型,我不會堵塞控制器並且不得不使用那個重複的代碼。

rescue_from CarrierWave::DownloadError, :with => :carrierwave_download_error 
    rescue_from CarrierWave::IntegrityError, :with => :carrierwave_integrity_error 

    def carrierwave_download_error 
    flash[:error] = "There was an error trying to download that remote file for upload. Please try again or download to your computer first." 
    redirect_to :back 
    end 

    def carrierwave_integrity_error 
    flash[:error] = "There was an error with that remote file for upload. It seems it's not a valid file." 
    redirect_to :back 
    end 
0

CarrierWave上的解決方案並不適用於我。正如Peter Hulst所說,CarrierWave在驗證之前加載文件。我發現了一個解決方法,通過在拋出異常時捕獲異常,並在稍後將其添加回驗證錯誤。出於某種原因,拋出異常時,所有其他記錄的屬性都將變爲零,因此在驗證之前還必須捕獲並重新添加它們。這些代碼都在你的模型中。

這仍然需要一點點修改才能使用來自配置的錯誤消息,而不是硬編碼。

attr_accessor :additional_error_message, :original_attributes 

def initialize(*args) 
    self.original_attributes = args[0] 
    begin 
    super 
    rescue CarrierWave::IntegrityError # bad file type 
    self.additional_error_message = 'must be a PNG, JPEG, or GIF file' # depends on your whitelist 
    rescue OpenURI::HTTPError # 404 
    self.additional_error_message = 'could not be found' 
    rescue RuntimeError # redirection 
    self.additional_error_message = 'could not be loaded' 
    rescue CarrierWave::DownloadError 
    self.additional_error_message = 'could not be loaded' 
    rescue 
    self.additional_error_message = 'could not be loaded' 
    end 
end 

before_validation do |image| 
    if additional_error_message.present? 
    errors.add(remote_image_url, additional_error_message) 
    self.name = original_attributes[:name] # replace this with re-adding all of your original attributes other than the remote_image_url 
    end 
end 

# the image will have an "is blank" error, this removes that 
after_validation do |image| 
    errors.delete(:image) if additional_error_message.present? 
end 
相關問題