Rails 4:Tempfile.read在第二次调用时不返回任何数据

时间:2014-10-13 16:18:40

标签: ruby-on-rails file-upload temporary-files

我使用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_typeoriginal_filesize会返回正确的值。

这是第二次调用的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]),则会调用两次回调。

上面提到的回调是在'地址'模型中。

1 个答案:

答案 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?