我使用before_validation
回调来保存文件输入中的数据。
def attach_document
if id_document_file
self.id_document = Document.create(:binary_data => id_document_file.read, :filetype => id_document_file.content_type, :filename => id_document_file.original_file, :filesize => id_document_file.size)
end
end
id_document_file
通过attr_accessor
定义并由控制器提供。问题是before_validation
有时会被调用两次。第一次一切按预期工作。但是在第二次调用时,read
方法不返回任何数据。奇怪的是,content_type
,original_file
和size
会返回正确的值。
这是第二次调用的SQL的样子:
SQL (1.2ms) INSERT INTO "documents" ("binary_data", "created_at", "filename", "filesize", "filetype", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["binary_data", "<0 bytes of binary data>"], ["created_at", Mon, 13 Oct 2014 16:39:57 CEST +02:00], ["filename", "sample.pdf"], ["filesize", 236991], ["filetype", "application/pdf"], ["updated_at", Mon, 13 Oct 2014 16:39:57 CEST +02:00]]
我在考虑使用文件大小作为解决方法(if id_document_file.size == 0
)来停止代码执行,但这显然不起作用,因为size
方法返回正确的文件大小。但主要问题是:为什么第二次调用没有返回任何数据?
更新
值得注意的是,我从两个不同的控制器中保存了模型。一个是users
控制器,另一个是addresses
控制器。模型之间的关系如下:
用户
has_one :address
地址
belongs_to :user
belongs_to :id_document, :class_name => 'Document'
当我从地址控制器调用@address.save
时,回调被调用一次。但是,如果我从用户控制器(之前使用@user.save
)调用@user.build_address(user_params[:address_attributes])
,则会调用两次回调。
上面提到的回调是在'地址'模型中。
答案 0 :(得分:0)
这里发生的事情是你正在用持久性调用触发before_validate,这就是为什么这个被称为两次的原因:
以下内容也会在第二次触发回调:
self.id_document = Document.create(:binary_data => id_document_file.read, :filetype => id_document_file.content_type, :filename => id_document_file.original_file, :filesize => id_document_file.size)
我也假设因为你可能在同一个调用堆栈中,所以该文件有一个锁(因为它在第一次调用file.read时仍然保持着它)。
我会尝试阻止这种重复的无意识行为开始,因为它现在看起来像是你的问题。
如果你真的想挖掘,并检查是否是这种情况,请参考以下SO帖子:
How can I check if a file is being used by other application?