I'm new to rails and building a simple bank statement converter app. User would select bank name, upload their statement, click "convert", and the converted file will be automatically downloaded.
How to access Rails ActionDispatch::::Http::UploadedFile attributes, in particular the content_type
attribute, in the controller? I would like to check for correct file type before passing the file for futher processing in the models by using that attribute in my validation methods.
I tried .content_type
and [:content_type]
, none worked, resulting in NoMethodError
even though the method is clearly defined as private method in the controller.
Here's my current application setup:
in the webpage, a form would allow user to submit
:bank
and:statement
params.in
ConvertersController
, the params are secured using the privateconverter_params
method, resulting in the following full params (as captured in server log):
Parameters: {"authenticity_token"=>"[FILTERED]", "converter"=>{"bank"=>"bank1", "statement"=>#<ActionDispatch::Http::UploadedFile:0x000055d9699140e0 @tempfile=#<Tempfile:/tmp/RackMultipart20210401-31472-dvsdde.pdf>, @original_filename="bank1.pdf", @content_type="application/pdf", @headers="Content-Disposition: form-data; name=\"converter[statement]\"; filename=\"bank1.pdf\"\r\nContent-Type: application/pdf\r\n">}, "commit"=>"convert"}
- Then in
:create
action, I appliedfile_check
private method onto the uploaded statement (i.e.converter_params[:statement]
) to check whether the file type is correct:
ConvertersController < ApplicationController
.
.
.
def create
@converter = Converter.new(converter_params)
if converter_params[:statement].nil?
flash.now[:alert] = "Error: no statement provided"
render action: "index"
elsif converter_params[:statement].file_check
flash.now[:alert] = "Error: wrong file type"
render action: "index"
else
result = @converter.run_conversion
file_path = Rails.root.join('public', 'output', result)
stream_then_delete_statement(file_path)
end
end
.
.
.
private
def converter_params
params.require(:converter).permit(:bank, :statement)
end
def file_check
pdf_statement = [ "bank1" ]
csv_statement = [ "bank2" ]
if pdf_statement.include? converter_params[:bank]
self.content_type.pdf_check?
elsif csv_statement.include? converter_params[:bank]
self.content_type.csv_check?
else
exit(0)
end
end
.
.
.
end
- then in the model, there are
csv_check?
andpdf_check?
methods that thefile_check
private method is referring to:
class MyModel < ActiveRecord::Base
def pdf_check?
self == "application/pdf"
end
def csv_check?
self == "application/csv"
end
.
.
.
end
However, currently I got NoMethodError
, even though the file_check
method is clearly defined as private method at the ConvertersController
. This error baffles me, as other private methods such as stream_then_delete_statement
is working normally.
full error:
NoMethodError in ConvertersController#create
undefined method `file_check' for #<ActionDispatch::Http::UploadedFile:0x000055d9699140e0 @tempfile=#<Tempfile:/tmp/RackMultipart20210401-31472-dvsdde.pdf>, @original_filename="bank1.pdf", @content_type="application/pdf", @headers="Content-Disposition: form-data; name=\"converter[statement]\"; filename=\"bank1.pdf\"\r\nContent-Type: application/pdf\r\n">