2011-05-16 18 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 
相关问题