如何解决无法将上传的文件传递给模型
| 我对Rails比较陌生,无法使以下代码正常工作。我正在尝试上传数据文件(Excel或csv),将其复制到temp文件夹,并在Datafiles模型中创建一条记录,该模型包含基本文件信息,例如文件名,类型和日期。然后,我想读取文件并使用数据在其他几个模型中创建或更新记录。如果一切顺利,请将文件移到一个永久位置,然后在Datafiles记录中写入新路径。 控制器:def new
@datafile = Datafile.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @datafile }
end
end
def create
@datafile = Datafile.new(params[:upload])
@datafile.save!
redirect_to datafile_path(@datafile),:notice => \"Successfully imported datafile\"
rescue => e
logger.error( \'Upload failed. \' + e.to_s )
flash[:error] = \'Upload failed. Please try again.\'
render :action => \'new\'
end
视图:
<%= form_for @datafile,:html => {:multipart => true} do |f| %>
<p>
<%= f.label(:upload,\"Select File:\") %>
<%= f.file_field :upload %>
</p>
<p> <%= f.submit \"Import\" %> </p>
<% end %>
模型:
require \'spreadsheet\'
class Datafile < ActiveRecord::Base
attr_accessor :upload
attr_accessible :upload
before_create :upload_file
def upload_file
begin
File.open(Rails.root.join(\'uploads/temp\',upload.original_filename),\'wb\') do |file|
file.write(upload.read)
self.filename = upload.original_filename
Spreadsheet.client_encoding = \'UTF-8\'
@book = Spreadsheet.open(file.path)
self.import
end
rescue => e
@upload_path = Rails.root.join(\'uploads/temp\',upload.original_filename)
File.delete(@upload_path) if File::exists?(@upload_path)
raise e
end
end
def import
case @book.worksheet(0).row(0)[0]
when \"WIP Report - Inception to Date\"
self.report_type = \'WIP\'
puts \'report_type assigned\'
self.import_wip
else
self.report_type = \'Unknown\'
end
end
def import_wip
self.end_date = @book.worksheet(0).row(0)[3]
puts \'end_date assigned\'
end
def formatted_end_date
end_date.strftime(\"%d %b,%Y\")
end
end
但是,它失败并且Rails服务器窗口显示
Started POST \"/datafiles\" for 127.0.0.1 at 2011-05-24 16:05:25 +0200
Processing by DatafilesController#create as HTML
Parameters: {\"utf8\"=>\"✓\",\"datafile\"=>{\"upload\"=>#<ActionDispatch::Http::UploadedFile:0xa0282d0 @original_filename=\"wip.xls\",@content_type=\"application/vnd.ms-excel\",@headers=\"Content-Disposition: form-data; name=\\\"datafile[upload]\\\"; filename=\\\"wip.xls\\\"\\r\\nContent-Type: application/vnd.ms-excel\\r\\n\",@tempfile=#<File:/tmp/RackMultipart20110524-14236-1kcu3hm>>},\"commit\"=>\"Import\"}
Upload failed. undefined method `original_filename\' for nil:NilClass
Rendered datafiles/new.html.erb within layouts/application (54.5ms)
Completed 200 OK in 131ms (Views: 56.3ms | ActiveRecord: 0.0ms)
我有通过的rspec模型测试和保存后无法重定向的控制器测试。如果有用的话,我可以发布它们。
我插入了raise @ datafile.to_yaml,并在终端中获得了以下内容。
ERROR RuntimeError: --- !ruby/object:Datafile
attributes:
filename:
report_type:
import_successful:
project:
begin_date:
end_date:
created_at:
updated_at:
attributes_cache: {}
changed_attributes: {}
destroyed: false
marked_for_destruction: false
persisted: false
previously_changed: {}
readonly: false
我注意到:upload没有列出。我可以从表单设置模型实例变量吗? :upload是一个实例变量,而不是一个属性,因为我不想将上传的文件保留在数据库中(只是其到本地目录的路径)。如果我不能以视图的形式设置实例变量,有什么建议吗? (就MVC而言)将文件上传到控制器中的temp文件夹,然后通过将其传递到temp文件的路径来创建模型记录是否有意义?
解决方法
您好,我是Rails的新手,我也为此感到困惑,我找到了一个解决方案,尽管它可能不是最好的。它确实可以工作。
在模型中创建一个名为import_upload的公共函数
def import_upload( upload )
@uploaded_file = upload
end
现在,您可以在控制器中显式传递它。我不知道如果您使用与file_field相同的名称创建attr_accsessor,为什么不会自动发生这种情况,但这是对我有用的解决方案。
def new
foo = Foo.new( params[:foo] )
foo.import_upload( params[:foo][:uploaded_file] ) #This is were the majic happens
#Do your saving stuff and call it a day
end
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。