未定义方法`[]'for#<actiondispatch :: http :: uploadedfile

时间:2016-05-23 21:32:57

标签: ruby-on-rails ruby heroku

=“”

我对Rails很新,我老实说对我正在做的事情感到困惑,抱歉遗漏了这里的任何基础......

related question没有帮助

尝试通过API将文件从iOS客户端应用程序上传到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)

1 个答案:

答案 0 :(得分: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