2016-05-23 91 views
1

我对Rails很陌生,我对我正在做的事感到困惑,对不起,遗漏了这里的任何基础知识......未定义的方法`[]'为#<ActionDispatch :: Http :: UploadedFile

related question没有帮助

尝试从iOS客户端应用程序通过API上传文件到Heroku上托管我的Rails应用程序。使用form.file_field上传时,安装Paperclip gem和文件上传效果很好。但不是来自API。

undefined method `[]' for #<ActionDispatch::Http::UploadedFile 

在做PUT方法在/ API/V1/FOOS上传文件/ 1

型号

class Foo < ActiveRecord::Base 

    has_attached_file :foo_file 
    validates_attachment : foo_file, content_type: { content_type: ["application/xml"] } 

end 

控制器

class Api::V1::FoosController < Api::V1::BaseController 

    def update 

    result = { status: "failed" } 

    begin 
     params[:foo_file] = parse_foo_file_data(params[:foo_file]) if params[:foo_file] 
     item = Foo.find(params[:id]) 
     item.foo_file = params[:foo_file] 

     if item.save 
     result[:status] = "success" 
     end 

    rescue Exception => e 
     Rails.logger.error "#{e.message}" 
    end 

    ensure 
     clean_tempfile 

    foo = Foo.find(params[:id]) 

    authorize foo 

    if !foo.update_attributes(update_params) 
     return api_error(status: 422, errors: foo.errors) 
    end 

    render json: result.to_json 

    end 

    def parse_foo_file_data(foo_file_data) 
    @tempfile = Tempfile.new('item_foo_file') 
    @tempfile.binmode 
    @tempfile.write Base64.decode64(foo_file_data.read) 
    @tempfile.rewind 

    uploaded_file = ActionDispatch::Http::UploadedFile.new(
     tempfile: @tempfile, 
     original_filename: foo_file_data.original_filename 
    ) 

    uploaded_file.content_type = foo_file_data.content_type 
    uploaded_file 
    end 

    def clean_tempfile 
    if @tempfile 
     @tempfile.close 
     @tempfile.unlink 
    end 
    end 

    def update_params 
    params.require(:app).permit(
    :name, :user_id, :foo_file 
    ) 
    end 
end 

最终我将不胜感激的任何援助获取此文件上传并附加到foo对象的foo_file参数。我认为这与我指出的未定义的方法错误有关。或者我可能完全脱离基地。感谢您的时间和帮助!

编辑:

新服务器日志

Started PUT "/api/v1/foos/1 

Processing by Foo::V1::FoosController#update as JSON 

Parameters: 
{"foo"=>{"name"=>"newnameB"}, "foo_file"=>#<ActionDispatch::Http::UploadedFile:0x007fac81c82168 @tempfile=#<Tempfile:/tmp/RackMultipart20160523-6-q6pyac.xml>, @original_filename="Main.xml", @content_type="multipart/form-data", @headers="Content-Disposition: form-data; name=\"foo_file\"; filename=\"Main.xml\"\r\nContent-Type: multipart/form-data\r\n">, "id"=>"1"} 

undefined method `gsub' for nil:NilClass 

Completed 200 OK in 25ms (Views: 0.4ms | ActiveRecord: 3.6ms) 
+0

你在这里有一个空间,打破了我的想法。 “:name,:user_id,:foo_file”应该是“:name,:user_id,:foo_file” –

+0

对不起,这只是我错误地将名字翻译成'foo'。我的实际代码中没有空格。我编辑了这篇文章。感谢您对细节的关注。 – Frankie

回答

0

update开始,在这条线:

params[:foo_file] = parse_foo_file_data(params[:foo_file]) if params[:foo_file] 

你打电话pase_foo_file_data(params[:foo_file])。您可以看到日志params[:foo_file]是否为ActionDispatch::Http::UploadedFile对象。

楼下,parse_foo_file_data的定义是这样的:

def parse_foo_file_data(foo_file_data) 
    @tempfile = Tempfile.new('item_foo_file') 
    @tempfile.binmode 
    @tempfile.write Base64.decode64(foo_file_data[:data]) 
    @tempfile.rewind 
    # ... etc 

更重要的是第三行,你有foo_file_data[:data]。但foo_file_data是一个ActionDispatch :: Http :: UploadedFile对象,并且that class doesn't provide a [] method

好像你最有可能正在试图做的是走出UploadedFile的对象的数据,在这种情况下,你要沿着@tempfile.write Base64.decode64(foo_file_data.read)

行更多的东西你会碰到类似的问题,当您尝试拨打foo_file_data[:content_type]进一步下来,那需要是foo_file_data.content_type

+0

这实际上是伟大的建议,它摆脱了我所遇到的错误。但该文件仍然不会上传到foo对象,并且我收到了“失败”的响应。但是现在日志中有一个不同的错误。有没有人看到另外的错误代码?我应该接受这个答案,然后再次发布问题? – Frankie

+0

在您粘贴的代码中没有直接调用'gsub',所以根据所提供的信息无法确定发生了什么。您可能想要记录异常回溯,而不是(或除了)该消息,例如'e.backtrace'。 – philomory

+0

此外,我只是注意到,但你_really_ [不应该抢救'例外]](http://daniel.fone.net.nz/blog/2013/05/28/why-you-should-never -rescue-exception-in-ruby /),它可以拯救像NoMemoryException或SystemStackError这样的事情。除非你有很好的理由,否则你应该拦截的最广泛的错误是StandardError。 – philomory

相关问题