ruby on rails - How can I have Grape return error messages in CSV format? -


i have rails app , have implemented api using grape gem. now, created custom error formatter (csvformatter) return error response in csv format.

and, have in application's v2.rb file:

error_formatter :csv, api::base::errors::csvformatter 

when hit url this:

http://example.com/api/v2/datasets/code/data.csv?&trim_start=06/01/99&trim_end=2014-05/28&sort_order=desc

it shows error in console , means custom error formatter working properly:

error  trim_start invalid  trim_end invalid 

but, need download error message in csv file. after looking @ grape's documentation, found way of setting content-type , tried this:

      rack = rack::response.new(as_csv , 422, { "content-type" => "text/csv" }).finish       rack[2].body[0] 

but, not working expected.

edit:

looks there no clean way of doing using grape without forcefully overriding status code according answer of simon. but, 1 may not wish may result other issues in application if other program tries read data api , gets incorrect response or without knowing why.

you're looking the content-disposition header. include in response this:

content-disposition: attachment; filename=error.csv 

and web browser treat response body file downloaded (to "error.csv", in example).

however, modifying code complicated 2 things:

  • from the grape source code it's apparent there's no way set response headers within error formatter, you'll need add custom exception handler formats response body , sets response headers appropriately each output format plan support.

  • according experimentation, browsers ignore content-disposition header if http status code indicates error (e.g. in 400 or 500 range), status code need overridden when user requests csv file.

try adding api class:

# handle exceptions error response appropriate requested # output format rescue_from :all |e|   # edit hash override http response status specific output   # formats   format_specific_status = {     :csv => 200   }    # edit hash add custom headers specific each output format   format_specific_headers = {     :csv => {       'content-disposition' => 'attachment; filename=error.csv'     }   }    # output format requested user   format = env['api.format']    # set http status appropriately requested output format ,   # error type   status = format_specific_status[format] ||              (e.respond_to? :status) && e.status ||              500    # set http headers appropriately requested format   headers = {     'content-type' => options[:content_types][format] || 'text/plain'   }.merge(format_specific_headers[format] || { })    # format message body using appropriate error formatter   error_formatter =     options[:error_formatters][format] || options[:default_error_formatter]   body = error_formatter.call(e.message, nil, options, env)    # return error response client in correct format   # correct http headers format   rack::response.new(body, status, headers).finish end 

now if configure api class handle 2 different formats (i've picked csv , plain-text here simplicity), this:

module errors   module csverrorformatter     def self.call(message, backtrace, options, env)       as_csv = "csv formatter:" + "\n"       message.split(",").each |msg|         as_csv += msg + "\n"       end        # note method returns response body       as_csv     end   end    module texterrorformatter     def self.call(message, backtrace, options, env)       as_txt = "text formatter:" + "\n"       message.split(",").each |msg|         as_txt += msg + "\n"       end        as_txt     end   end end  content_type :csv, 'text/csv' content_type :txt, 'text/plain'  error_formatter :csv, api::base::errors::csverrorformatter error_formatter :txt, api::base::errors::texterrorformatter 

you should find api returns error response suitable requested format, , triggers browser download response when csv format requested. naturally can extended support many formats like, explicitly declaring content types , error formatters.

note there's 1 case in code doesn't automatically right thing, , that's when error response invoked directly using error!. in case you'll have supply correct body , headers part of call itself. i'll leave extracting relevant parts of above code reusable methods exercise reader.


Comments

Popular posts from this blog

google api - Incomplete response from Gmail API threads.list -

Installing Android SQLite Asset Helper -

Qt Creator - Searching files with Locator including folder -