我有一个ImagesController
启动了一个非平凡的保存操作。这是高级背景:
我的应用程序中有几种不同的物理文件类型可供处理。这些belongs_to
中的每一个Binary
。当然,可以创建文件,这个过程涉及将物理文件上传到临时位置,可能验证物理文件(大小,类型或其他)然后,假设没有问题,移动在相应表格中创建数据库记录之前将文件归档到永久位置(为了我的问题,我们使用images
和binaries
)。
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,如何强制保存操作失败?
感谢。
答案 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等 返回错误
然后在控制器中相应地操作。