强制保存!操作失败

时间:2009-08-19 23:32:25

标签: ruby-on-rails

我有一个ImagesController启动了一个非平凡的保存操作。这是高级背景:

我的应用程序中有几种不同的物理文件类型可供处理。这些belongs_to中的每一个Binary。当然,可以创建文件,这个过程涉及将物理文件上传到临时位置,可能验证物理文件(大小,类型或其他)然后,假设没有问题,移动在相应表格中创建数据库记录之前将文件归档到永久位置(为了我的问题,我们使用imagesbinaries)。

Image属于Binary,并且BinaryObserver会观察Image类。在该观察者类中,有一个before_create()方法告诉Binary类上传图像的物理文件并将相关记录保存在数据库中(包括名称,路径,URI信息等)。 / p>

观察者类方法所做的一件事是测试原始模型中的回调方法,在这种情况下为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,如何强制保存操作失败?

感谢。

2 个答案:

答案 0 :(得分: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 :(得分:0)

您的观察者仍然在基本上在顶部创建的ActiveRecord事务中运行。所以数据库明智,你应该仍然有诚信。但是为了将该信息传递到顶部,我会在返回false之前在对象中设置一个实例变量。由于控制器仍然在与Observer相同的对象上运行,因此可以获得相同的信息。

...在你的观察者中 model.is_valid = false#or_something_went_wrong = true等 返回错误

然后在控制器中相应地操作。