What is the formula for setting WEB_CONCURRENCY on heroku? - ruby-on-rails
I am frequently getting this error Memory quota exceeded for my ruby on rails application hosted on heroku:
2014-12-29 11:09:37.876 355 <45>1 2014-12-29T11:09:37.210533+00:00 heroku worker.1 - - source=worker.1 dyno=heroku.22144543.00c11b4d-8ec6-46d9-addf-f03163e10f0c sample#memory_total=2899.25MB sample#memory_rss=1023.73MB sample#memory_cache=0.00MB sample#memory_swap=1875.52MB sample#memory_pgpgin=2603236pages sample#memory_pgpgout=2341160pages
2014-12-29 11:09:37.876 132 <4
2014-12-29 11:09:37.876 132 <455>1 2014-12-29T11:09:37.210533+00:00 heroku worker.1 - - Process running mem=2899M(283.1%)>1 2014-12-29T11:09:37.210533+00:00 heroku worker.1 - - Error R14 (Memory quota exceeded)
I read the blog of which suggests the solution i.e. set WEB_CONCURRENCY config variable but it is not clear to me.
My current configuration on heroku are:
config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 29
preload_app true
Edited:
Worker Code
class PhotoWorker
include Sidekiq::Worker
sidekiq_options queue: "high"
# sidekiq_options retry: false
def perform(params)
begin
puts "Start Woker for #{params.inspect}"
site = Site.find params['site_id']
if params["id"].present?
photo = Photo.find(params["id"])
if params['key'].present?
photo.key = params['key']
photo.remote_image_url = photo.image.direct_fog_url(:with_path => true)
photo.image_name = params['key'].split('/').last
photo.save(validate: false)
puts photo.inspect
end
else
#photo = site.photos.build
#photo.hotel_detail_id = site.hotel_detail.id
#photo.album_id = site.hotel_detail.album.id
#photo.save(validate: false)
photo.key = params['key']
photo.remote_image_url = photo.image.direct_fog_url(:with_path => true)
#photo.image = params['key']
#photo.remote_image_url = params['key']
photo.image_name = params['key'].split('/').last
puts photo.inspect
photo.save(validate: false)
end
if params["id"].present? && params["crop_x"].present?
photo.crop_x = params["crop_x"]
photo.crop_y = params["crop_y"]
photo.crop_w = params["crop_w"]
photo.crop_h = params["crop_h"]
photo.save(validate: false)
end
if params["id"].present?
if params['key'].present?
s3 = AWS::S3.new.buckets[ENV["FOG_DIRECTORY"]]
s3.objects[params['key']].delete
end
else
AmazonFile.new(params['key']).delete
end
puts "Deleted temp file: #{params['key']}" if params['key'].present?
puts "Photo(#{photo.id}) saved successfully. URL: #{params['key']}"
rescue Exception => exc
#puts "Photo not saved. URL: #{params['key']}"
puts "Error: #{exc.message}"
end
end
end
Apart from sidekiq i am also using carrierwave_backgrounder gem.
I am using Kraken for image compression
Photo Uploader
class PhotoUploader < CarrierWave::Uploader::Base
#include ::CarrierWave::Backgrounder::Delay
include CarrierWaveDirect::Uploader
include CarrierWave::MiniMagick
include CarrierWave::MimeTypes
process :set_content_type
process :crop
storage :fog
after :store, :kraken
version :admin do
process :resize_to_fit => [200,200]
end
#Leisure theme
version :leisure_358x243, :if => :leisure_theme? do
process :resize_to_fill => [358,243]
end
version :leisure_900x500, :if => :leisure_theme? do
process :resize_to_fill => [900,500]
end
version :leisure_350x147, :if => :leisure_theme? do
process :resize_to_fill => [350,147]
end
version :leisure_1100x344, :if => :leisure_theme? do
process :resize_to_fill => [1100,344]
end
#Business theme
version :business_360x160, :if => :business_theme? do
process :resize_to_fill => [360,160]
end
version :business_1100x315, :if => :business_theme? do
process :resize_to_fill => [1100,315]
end
version :business_1140x530, :if => :business_theme? do
process :resize_to_fill => [1140,530]
end
version :business_1100x355, :if => :business_theme? do
process :resize_to_fill => [1100,355]
end
#Commthree theme
version :commthree_550x300, :if => :commthree_theme? do
process :resize_to_fill => [550,300]
end
version :commthree_319x183, :if => :commthree_theme? do
process :resize_to_fill => [319,183]
end
version :commthree_1920x700, :if => :commthree_theme? do
process :resize_to_fill => [1920,700]
end
#All theme
version :all_360x188 do
process :resize_to_fill => [360,188]
end
version :all_1100x401 do
process :resize_to_fill => [1100,401]
end
version :all_140x88 do
process :resize_to_fill => [140,88]
end
def kraken(file)
if version_name.to_s == ""
storepath = store_dir + "/" + filename
else
fname = filename.split('.')
#originalfile = "http://s3.amazonaws.com/" + ENV["FOG_DIRECTORY"] + "/" + store_dir + "/" + fname[0] + "_" + version_name.to_s + "." + fname.last
storepath = store_dir + "/" + fname[0] + "_" + version_name.to_s + "." + fname.last
end
originalfile = "http://s3.amazonaws.com/" + ENV["FOG_DIRECTORY"] + "/" + store_dir + "/" + filename
kraken = Kraken::API.new(
:api_key => ENV['KRAKEN_API'],
:api_secret => ENV['KRAKEN_SECRET']
)
params = {}
Rails.logger.info('Kraken About to Process: ' + originalfile);
p "version #{version_name}"
case version_name.to_s
when "admin"
params = {
'lossy' => true,
'resize' => {
'width' => 200,
'height' => 200,
'strategy' => "auto",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "leisure_358x243"
params = {
'lossy' => true,
'resize' => {
'width' => 358,
'height' => 243,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "leisure_900x500"
params = {
'lossy' => true,
'resize' => {
'width' => 900,
'height' => 500,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "leisure_350x147"
params = {
'lossy' => true,
'resize' => {
'width' => 350,
'height' => 147,
'strategy' => "exact",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "leisure_1100x344"
params = {
'lossy' => true,
'resize' => {
'width' => 1100,
'height' => 344,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "business_360x160"
params = {
'lossy' => true,
'resize' => {
'width' => 360,
'height' => 160,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "business_1100x315"
params = {
'lossy' => true,
'resize' => {
'width' => 1100,
'height' => 315,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "business_1140x530"
params = {
'lossy' => true,
'resize' => {
'width' => 1140,
'height' => 530,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "business_1100x355"
params = {
'lossy' => true,
'resize' => {
'width' => 1100,
'height' => 355,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "commthree_550x300"
params = {
'lossy' => true,
'resize' => {
'width' => 550,
'height' => 300,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "commthree_319x183"
params = {
'lossy' => true,
'resize' => {
'width' => 319,
'height' => 183,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "commthree_1920x700"
params = {
'lossy' => true,
'resize' => {
'width' => 1920,
'height' => 700,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "all_360x188"
params = {
'lossy' => true,
'resize' => {
'width' => 360,
'height' => 188,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "all_1100x401"
params = {
'lossy' => true,
'resize' => {
'width' => 1100,
'height' => 401,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
when "all_140x88"
params = {
'lossy' => true,
'resize' => {
'width' => 140,
'height' => 88,
'strategy' => "fit",
},
's3_store' => {
'key' => ENV['AWS_ACCESS_KEY_ID'],
'secret' => ENV["AWS_SECRET_ACCESS_KEY"],
'bucket' => ENV["FOG_DIRECTORY"],
'acl' => 'public_read',
'path' => storepath
},
}
end
#Store the file online
if !version_name.blank?
Rails.logger.info('UPLOADING TO: ' + store_path);
data = kraken.url(originalfile,params)
if data.success
Rails.logger.info('KRAKEN: Success! Optimized image URL: ' + data.kraked_url)
else
puts
Rails.logger.info('KRAKEN: Fail. Error message: ' + data.message)
end
end
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png)
end
# def cache_dir
# "#{Rails.root}/tmp/uploads"
# end
def store_dir
if model.id.present?
"photos/#{model.id}"
else
"photos"
end
end
#file name is missing extension!!!
def filename
original_filename if original_filename.present?
end
def crop
puts "i am uploader"
if model.crop_x.present?
manipulate! do |img|
puts "i am cropping"
cx = model.crop_x.to_i
cy = model.crop_y.to_i
cw = model.crop_w.to_i
ch = model.crop_h.to_i
img.crop"#{cw}x#{ch}+#{cx}+#{cy}"
#img
end
end
end
def business_theme? (image)
p "model:#{model.id}"
(model.hotel_detail.site.theme.layout == "x1")if model.id.present?
end
def leisure_theme? (image)
p "model:#{model.id}"
(model.hotel_detail.site.theme.layout == "x2")if model.id.present?
end
def commthree_theme? (image)
p "model:#{model.id}"
(model.hotel_detail.site.theme.layout == "x3") if model.id.present?
end
protected
def secure_token(length=16)
var = :"##{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.hex(length/2))
end
end
Please suggest me how to calculate the correct value of WEB_CONCURRENCY.
It looks like you are using both minimagick and kraken to do image manipulation. If you fully migrate to Kraken and let them handle all of your image manipulation you shouldn't have a problem with memory on your workers.
Remove all of your versions and see if that improves performance.
version :leisure_358x243, :if => :leisure_theme? do
process :resize_to_fill => [358,243]
end
If you want to stick with processing images on your workers there are more efficient libraries than carrierwave-minimagick. Take a look at carrierwave-vips.
There is no "magic formula" - as per the Heroku docs for Deploying Rails Applications on Unicorn - Caveats:
Each forked OS process consumes additional memory. This limits how
many processes you can run in a single dyno. With a typical Rails
memory footprint, you can expect to run 2-4 Unicorn worker processes.
Your application may allow for more or less processes depending on
your specific memory footprint, and we recommend specifying this
number in an config var to allow for faster application tuning.
Additionally, specific versions of Ruby run better on Heroku than others, due to memory leaks. I strongly suggest Ruby 2.0.0 for the best memory maintenance with the New Relic gem, as the latest New Relic gem has evidence of a memory leak. I personally had issues with the New Relic gem on Ruby 2.1.1, 2.1.3, and 2.1.4. I've since downgraded to 2.0.0, which cut my memory usage in half.
However, if you're concerned about performance of Ruby 2.0.0, you might want to check out an alternative to New Relic, at least until New Relic patches the memory leak in their latest gem.
Just to react about CDub's answer. I had a couple of memory issues with the last Ruby version. Yes, New Relic seems to use a lot of memory but it's not the reason of those Memory quota exceeded errors.
After reading a lot of posts talking about that problem, it seems that the real cause come from the Ruby GC, which is causing a lot of server swapping since version 2.1.x .
To fix that I just set RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR to a value around 1.25.
You can play with that setting to find the best value for your environment.
FYI my app is running with Ruby 2.1.5 on Heroku Cedar 14
Hope it helps :)
Related
Elfinder Rails and Amazon S3
I am using Elfinder Rails for Media Manger in my application. I am working on to store the media files to Amazon S3 storage. I try to use the gem el_finder_s3. I created bucket and provided all the configurations like. def elfinder ElFinderS3::Connector.new( :mime_handler => ElFinderS3::MimeType, :root => '/', :url => 's3.ap-southeast-1.amazonaws.com', :thumbs => true, :thumbs_size => 100, :thumbs_directory => 'thumbs', :home => t('admin.media.home'), :original_filename_method => lambda { |file| "#{File.basename(file.original_filename, File.extname(file.original_filename)).parameterize}#{File.extname(file.original_filename)}" }, :default_perms => {:read => true, :write => true, :rm => true, :hidden => false}, :server => { :bucket_name => 'bucket_name', :region => 'ap-southeast-1', :access_key_id => 'acces_key', :secret_access_key => 'secret_key', :cdn_base_path => 's3.ap-southeast-1.amazonaws.com' } ).run(params) end Rails application is connect with S3 but elfinder doesn't show the file contents. I checked the bucket, thumb folder was created but elfinder was unable to load the contents. Please help me to fix it.
It is fixed with the update of the above script. Here is the updated script. def elfinder h, r = ElFinderS3::Connector.new( :mime_handler => ElFinderS3::MimeType, :root => '/', :url => 's3.ap-southeast-1.amazonaws.com', :thumbs => true, :thumbs_size => 100, :thumbs_directory => 'thumbs', :home => t('admin.media.home'), :original_filename_method => lambda { |file| "#{File.basename(file.original_filename, File.extname(file.original_filename)).parameterize}#{File.extname(file.original_filename)}" }, :default_perms => {:read => true, :write => true, :rm => true, :hidden => false}, :server => { :bucket_name => 'bucket_name', :region => 'ap-southeast-1', :access_key_id => 'acces_key', :secret_access_key => 'secret_key', :cdn_base_path => 's3.ap-southeast-1.amazonaws.com' } ).run(params) headers.merge!(h) if r.empty? (render :nothing => true) and return end render :json => r, :layout => false end
Get action name in model rails 4
I am using paperclip to upload files in my rail4 project. Now I need to apply some condition based on the name of controller action that is currently uploading the attachment file. Can someone please help me get the name of currently used action in model. Thanks in advance. UPDATE: Here is my code in modal file: has_attached_file :attachment, :styles => lambda { |attachment| {:medium => attachment.instance.video? ? { :geometry => "236x236>", :format => 'jpg', :time => 10 } : { :geometry => "236x236>" }, :thumb => attachment.instance.video? ? { :geometry => "150x150>", :format => 'jpg', :time => 10 } : { :geometry => "150x150>" },:large => attachment.instance.video? ? { :geometry => "1000x700", :format => 'jpg', :time => 10 } : { :geometry => "1000x700" }} },:processors => lambda { |a| a.video? ? [ :transcoder ] : [ :cropper ] } before_post_process :is_audio? def is_audio? return false if [ 'audio/mp3','audio/mpeg'].include?(attachment.content_type) end Now I want to skip processors and styles and keep only the original file (just like here in case of audio file) if file is uploaded from update action. Please suggest.
Async video processing in rails and paperclip
I'm using gem 'paperclip-av-transcoder', "0.6.2" for my video processing. I simply need to write this code to have my video converted into many formats: has_attached_file :video, :styles => { :mp4 => { :format => 'mp4', :convert_options => { :output => { :vcodec => 'libx264', :acodec => 'copy' } } }, :ogg => { :format => 'ogg', :auto_rotate => true }, :webm => { :format => 'webm', :auto_rotate => true }, :flv => { :format => 'flv', :convert_options => { :output => { :ar => 44100 } }, :auto_rotate => true }, :thumb => { :geometry => "300x300#", :format => 'jpg', :time => 1, :auto_rotate => true } }, :processors => [:transcoder] But this code is synchronous and the user that upload the video is stuck during the conversion. I would like to add an async wrapper (worker) around :transcoder so I can call: has_attached_file :video, :styles => {... }, :processors => [:wrapper_transcoder_worker] I have installed resque and redis and everything work. Do you have an idea on how can I write the asynch worker around transcoder?
Have you tried delayed_paperclip gem? It pushes all processing into background and supports resque (among others).
lock paperclip at version 4.2.0
how to download files with different extension with send_file command
I have the following code, I want to download files of different mime types. Ie docx, pdf etc. I have defined my download action, then bellow am trying to get the file extension for which i direct it to the correct mimetype. But this doesnot seem to work def download #uploadedfile = Uploadedfile.find(params[:id]) send_data( #uploadedfile.upload_file.path, :filename => #uploadedfile.name, # :type => 'application/pdf', # :type=>"*/*", # :type=> "application/vnd.openxmlformats-officedocument.wordprocessingml.document", #:type=> MIME::Types.type_for(#uploadedfile.name).to_s, #:content_type => %w(application/vnd.openxmlformats-officedocument.wordprocessingml.document application/pdf), :type=> file_extension, :stream => true, :x_sendfile=>true, :url_based_filename => true ) flash[:notice] = "The file has been downloaded" end def file_extension #uploadedfile = Uploadedfile.find(params[:id]) # ext = File.extname("#{#uploadedfile.name}") ext = File.extname(#uploadedfile.name) if (ext == ".pdf") content_type = "application/pdf" elsif (ext == ".doc") || ( ext == ".rtf") || ( ext == ".docx") content_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" elsif (ext == ".txt") content_type = "text/Plain" elsif (ext == ".rar") content_type = "Application/x-rar-compressed" elsif (ext == ".jpeg" || ext==".jpg") content_type = "image/jpeg" else content_type = "Application/octet-stream" end content_type end but this seems not to work, where am i going wrong? Please help
Here's how i do this. In config/initializers/constants.rb MIME_TYPES_FROM_EXTENSION = { ".3dm" => "x-world/x-3dmf", ".3dmf" => "x-world/x-3dmf", ".a" => "application/octet-stream", ".aab" => "application/x-authorware-bin", ".aam" => "application/x-authorware-map", ".aas" => "application/x-authorware-seg", ".abc" => "text/vnd.abc", ".acgi" => "text/html", ".afl" => "video/animaflex", ".ai" => "application/postscript", ".aif" => "audio/aiff", ".aif" => "audio/x-aiff", ".aifc" => "audio/aiff", ".aifc" => "audio/x-aiff", ".aiff" => "audio/aiff", ".aiff" => "audio/x-aiff", ".aim" => "application/x-aim", ".aip" => "text/x-audiosoft-intra", ".ani" => "application/x-navi-animation", ".aos" => "application/x-nokia-9000-communicator-add-on-software", ".aps" => "application/mime", ".arc" => "application/octet-stream", ".arj" => "application/arj", ".arj" => "application/octet-stream", ".art" => "image/x-jg", ".asf" => "video/x-ms-asf", ".asm" => "text/x-asm", ".asp" => "text/asp", ".asx" => "application/x-mplayer2", ".asx" => "video/x-ms-asf", ".asx" => "video/x-ms-asf-plugin", ".au" => "audio/basic", ".au" => "audio/x-au", ".avi" => "application/x-troff-msvideo", ".avi" => "video/avi", ".avi" => "video/msvideo", ".avi" => "video/x-msvideo", ".avs" => "video/avs-video", ".bcpio" => "application/x-bcpio", ".bin" => "application/mac-binary", ".bin" => "application/macbinary", ".bin" => "application/octet-stream", ".bin" => "application/x-binary", ".bin" => "application/x-macbinary", ".bm" => "image/bmp", ".bmp" => "image/bmp", ".bmp" => "image/x-windows-bmp", ".boo" => "application/book", ".book" => "application/book", ".boz" => "application/x-bzip2", ".bsh" => "application/x-bsh", ".bz" => "application/x-bzip", ".bz2" => "application/x-bzip2", ".c" => "text/plain", ".c" => "text/x-c", ".c++" => "text/plain", ".cat" => "application/vnd.ms-pki.seccat", ".cc" => "text/plain", ".cc" => "text/x-c", ".ccad" => "application/clariscad", ".cco" => "application/x-cocoa", ".cdf" => "application/cdf", ".cdf" => "application/x-cdf", ".cdf" => "application/x-netcdf", ".cer" => "application/pkix-cert", ".cer" => "application/x-x509-ca-cert", ".cha" => "application/x-chat", ".chat" => "application/x-chat", ".class" => "application/java", ".class" => "application/java-byte-code", ".class" => "application/x-java-class", ".com" => "application/octet-stream", ".com" => "text/plain", ".conf" => "text/plain", ".cpio" => "application/x-cpio", ".cpp" => "text/x-c", ".cpt" => "application/mac-compactpro", ".cpt" => "application/x-compactpro", ".cpt" => "application/x-cpt", ".crl" => "application/pkcs-crl", ".crl" => "application/pkix-crl", ".crt" => "application/pkix-cert", ".crt" => "application/x-x509-ca-cert", ".crt" => "application/x-x509-user-cert", ".csh" => "application/x-csh", ".csh" => "text/x-script.csh", ".css" => "application/x-pointplus", ".css" => "text/css", ".cxx" => "text/plain", ".dcr" => "application/x-director", ".deepv" => "application/x-deepv", ".def" => "text/plain", ".der" => "application/x-x509-ca-cert", ".dif" => "video/x-dv", ".dir" => "application/x-director", ".dl" => "video/dl", ".dl" => "video/x-dl", ".doc" => "application/msword", ".dot" => "application/msword", ".dp" => "application/commonground", ".drw" => "application/drafting", ".dump" => "application/octet-stream", ".dv" => "video/x-dv", ".dvi" => "application/x-dvi", ".dwf" => "drawing/x-dwf (old)", ".dwf" => "model/vnd.dwf", ".dwg" => "application/acad", ".dwg" => "image/vnd.dwg", ".dwg" => "image/x-dwg", ".dxf" => "application/dxf", ".dxf" => "image/vnd.dwg", ".dxf" => "image/x-dwg", ".dxr" => "application/x-director", ".el" => "text/x-script.elisp", ".elc" => "application/x-bytecode.elisp (compiled elisp)", ".elc" => "application/x-elc", ".env" => "application/x-envoy", ".eps" => "application/postscript", ".es" => "application/x-esrehber", ".etx" => "text/x-setext", ".evy" => "application/envoy", ".evy" => "application/x-envoy", ".exe" => "application/octet-stream", ".f" => "text/plain", ".f" => "text/x-fortran", ".f77" => "text/x-fortran", ".f90" => "text/plain", ".f90" => "text/x-fortran", ".fdf" => "application/vnd.fdf", ".fif" => "application/fractals", ".fif" => "image/fif", ".fli" => "video/fli", ".fli" => "video/x-fli", ".flo" => "image/florian", ".flx" => "text/vnd.fmi.flexstor", ".fmf" => "video/x-atomic3d-feature", ".for" => "text/plain", ".for" => "text/x-fortran", ".fpx" => "image/vnd.fpx", ".fpx" => "image/vnd.net-fpx", ".frl" => "application/freeloader", ".funk" => "audio/make", ".g" => "text/plain", ".g3" => "image/g3fax", ".gif" => "image/gif", ".gl" => "video/gl", ".gl" => "video/x-gl", ".gsd" => "audio/x-gsm", ".gsm" => "audio/x-gsm", ".gsp" => "application/x-gsp", ".gss" => "application/x-gss", ".gtar" => "application/x-gtar", ".gz" => "application/x-compressed", ".gz" => "application/x-gzip", ".gzip" => "application/x-gzip", ".gzip" => "multipart/x-gzip", ".h" => "text/plain", ".h" => "text/x-h", ".hdf" => "application/x-hdf", ".help" => "application/x-helpfile", ".hgl" => "application/vnd.hp-hpgl", ".hh" => "text/plain", ".hh" => "text/x-h", ".hlb" => "text/x-script", ".hlp" => "application/hlp", ".hlp" => "application/x-helpfile", ".hlp" => "application/x-winhelp", ".hpg" => "application/vnd.hp-hpgl", ".hpgl" => "application/vnd.hp-hpgl", ".hqx" => "application/binhex", ".hqx" => "application/binhex4", ".hqx" => "application/mac-binhex", ".hqx" => "application/mac-binhex40", ".hqx" => "application/x-binhex40", ".hqx" => "application/x-mac-binhex40", ".hta" => "application/hta", ".htc" => "text/x-component", ".htm" => "text/html", ".html" => "text/html", ".htmls" => "text/html", ".htt" => "text/webviewhtml", ".htx" => "text/html", ".ice" => "x-conference/x-cooltalk", ".ico" => "image/x-icon", ".idc" => "text/plain", ".ief" => "image/ief", ".iefs" => "image/ief", ".iges" => "application/iges", ".iges" => "model/iges", ".igs" => "application/iges", ".igs" => "model/iges", ".ima" => "application/x-ima", ".imap" => "application/x-httpd-imap", ".inf" => "application/inf", ".ins" => "application/x-internett-signup", ".ip" => "application/x-ip2", ".isu" => "video/x-isvideo", ".it" => "audio/it", ".iv" => "application/x-inventor", ".ivr" => "i-world/i-vrml", ".ivy" => "application/x-livescreen", ".jam" => "audio/x-jam", ".jav" => "text/plain", ".jav" => "text/x-java-source", ".java" => "text/plain", ".java" => "text/x-java-source", ".jcm" => "application/x-java-commerce", ".jfif" => "image/jpeg", ".jfif" => "image/pjpeg", ".jfif-tbnl" => "image/jpeg", ".jpe" => "image/jpeg", ".jpe" => "image/pjpeg", ".jpeg" => "image/jpeg", ".jpeg" => "image/pjpeg", ".jpg" => "image/jpeg", ".jpg" => "image/pjpeg", ".jps" => "image/x-jps", ".js" => "application/x-javascript", ".jut" => "image/jutvision", ".kar" => "audio/midi", ".kar" => "music/x-karaoke", ".ksh" => "application/x-ksh", ".ksh" => "text/x-script.ksh", ".la" => "audio/nspaudio", ".la" => "audio/x-nspaudio", ".lam" => "audio/x-liveaudio", ".latex" => "application/x-latex", ".lha" => "application/lha", ".lha" => "application/octet-stream", ".lha" => "application/x-lha", ".lhx" => "application/octet-stream", ".list" => "text/plain", ".lma" => "audio/nspaudio", ".lma" => "audio/x-nspaudio", ".log" => "text/plain", ".lsp" => "application/x-lisp", ".lsp" => "text/x-script.lisp", ".lst" => "text/plain", ".lsx" => "text/x-la-asf", ".ltx" => "application/x-latex", ".lzh" => "application/octet-stream", ".lzh" => "application/x-lzh", ".lzx" => "application/lzx", ".lzx" => "application/octet-stream", ".lzx" => "application/x-lzx", ".m" => "text/plain", ".m" => "text/x-m", ".m1v" => "video/mpeg", ".m2a" => "audio/mpeg", ".m2v" => "video/mpeg", ".m3u" => "audio/x-mpequrl", ".man" => "application/x-troff-man", ".map" => "application/x-navimap", ".mar" => "text/plain", ".mbd" => "application/mbedlet", ".mc$" => "application/x-magic-cap-package-1.0", ".mcd" => "application/mcad", ".mcd" => "application/x-mathcad", ".mcf" => "image/vasa", ".mcf" => "text/mcf", ".mcp" => "application/netmc", ".me" => "application/x-troff-me", ".mht" => "message/rfc822", ".mhtml" => "message/rfc822", ".mid" => "application/x-midi", ".mid" => "audio/midi", ".mid" => "audio/x-mid", ".mid" => "audio/x-midi", ".mid" => "music/crescendo", ".mid" => "x-music/x-midi", ".midi" => "application/x-midi", ".midi" => "audio/midi", ".midi" => "audio/x-mid", ".midi" => "audio/x-midi", ".midi" => "music/crescendo", ".midi" => "x-music/x-midi", ".mif" => "application/x-frame", ".mif" => "application/x-mif", ".mime" => "message/rfc822", ".mime" => "www/mime", ".mjf" => "audio/x-vnd.audioexplosion.mjuicemediafile", ".mjpg" => "video/x-motion-jpeg", ".mm" => "application/base64", ".mm" => "application/x-meme", ".mme" => "application/base64", ".mod" => "audio/mod", ".mod" => "audio/x-mod", ".moov" => "video/quicktime", ".mov" => "video/quicktime", ".movie" => "video/x-sgi-movie", ".mp2" => "audio/mpeg", ".mp2" => "audio/x-mpeg", ".mp2" => "video/mpeg", ".mp2" => "video/x-mpeg", ".mp2" => "video/x-mpeq2a", ".mp3" => "audio/mpeg3", ".mp3" => "audio/x-mpeg-3", ".mp3" => "video/mpeg", ".mp3" => "video/x-mpeg", ".mpa" => "audio/mpeg", ".mpa" => "video/mpeg", ".mpc" => "application/x-project", ".mpe" => "video/mpeg", ".mpeg" => "video/mpeg", ".mpg" => "audio/mpeg", ".mpg" => "video/mpeg", ".mpga" => "audio/mpeg", ".mpp" => "application/vnd.ms-project", ".mpt" => "application/x-project", ".mpv" => "application/x-project", ".mpx" => "application/x-project", ".mrc" => "application/marc", ".ms" => "application/x-troff-ms", ".mv" => "video/x-sgi-movie", ".my" => "audio/make", ".mzz" => "application/x-vnd.audioexplosion.mzz", ".nap" => "image/naplps", ".naplps" => "image/naplps", ".nc" => "application/x-netcdf", ".ncm" => "application/vnd.nokia.configuration-message", ".nif" => "image/x-niff", ".niff" => "image/x-niff", ".nix" => "application/x-mix-transfer", ".nsc" => "application/x-conference", ".nvd" => "application/x-navidoc", ".o" => "application/octet-stream", ".oda" => "application/oda", ".omc" => "application/x-omc", ".omcd" => "application/x-omcdatamaker", ".omcr" => "application/x-omcregerator", ".p" => "text/x-pascal", ".p10" => "application/pkcs10", ".p10" => "application/x-pkcs10", ".p12" => "application/pkcs-12", ".p12" => "application/x-pkcs12", ".p7a" => "application/x-pkcs7-signature", ".p7c" => "application/pkcs7-mime", ".p7c" => "application/x-pkcs7-mime", ".p7m" => "application/pkcs7-mime", ".p7m" => "application/x-pkcs7-mime", ".p7r" => "application/x-pkcs7-certreqresp", ".p7s" => "application/pkcs7-signature", ".part" => "application/pro_eng", ".pas" => "text/pascal", ".pbm" => "image/x-portable-bitmap", ".pcl" => "application/vnd.hp-pcl", ".pcl" => "application/x-pcl", ".pct" => "image/x-pict", ".pcx" => "image/x-pcx", ".pdb" => "chemical/x-pdb", ".pdf" => "application/pdf", ".pfunk" => "audio/make", ".pfunk" => "audio/make.my.funk", ".pgm" => "image/x-portable-graymap", ".pgm" => "image/x-portable-greymap", ".pic" => "image/pict", ".pict" => "image/pict", ".pkg" => "application/x-newton-compatible-pkg", ".pko" => "application/vnd.ms-pki.pko", ".pl" => "text/plain", ".pl" => "text/x-script.perl", ".plx" => "application/x-pixclscript", ".pm" => "image/x-xpixmap", ".pm" => "text/x-script.perl-module", ".pm4" => "application/x-pagemaker", ".pm5" => "application/x-pagemaker", ".png" => "image/png", ".pnm" => "application/x-portable-anymap", ".pnm" => "image/x-portable-anymap", ".pot" => "application/mspowerpoint", ".pot" => "application/vnd.ms-powerpoint", ".pov" => "model/x-pov", ".ppa" => "application/vnd.ms-powerpoint", ".ppm" => "image/x-portable-pixmap", ".pps" => "application/mspowerpoint", ".pps" => "application/vnd.ms-powerpoint", ".ppt" => "application/mspowerpoint", ".ppt" => "application/powerpoint", ".ppt" => "application/vnd.ms-powerpoint", ".ppt" => "application/x-mspowerpoint", ".ppz" => "application/mspowerpoint", ".pre" => "application/x-freelance", ".prt" => "application/pro_eng", ".ps" => "application/postscript", ".psd" => "application/octet-stream", ".pvu" => "paleovu/x-pv", ".pwz" => "application/vnd.ms-powerpoint", ".py" => "text/x-script.phyton", ".pyc" => "applicaiton/x-bytecode.python", ".qcp" => "audio/vnd.qcelp", ".qd3" => "x-world/x-3dmf", ".qd3d" => "x-world/x-3dmf", ".qif" => "image/x-quicktime", ".qt" => "video/quicktime", ".qtc" => "video/x-qtc", ".qti" => "image/x-quicktime", ".qtif" => "image/x-quicktime", ".ra" => "audio/x-pn-realaudio", ".ra" => "audio/x-pn-realaudio-plugin", ".ra" => "audio/x-realaudio", ".ram" => "audio/x-pn-realaudio", ".ras" => "application/x-cmu-raster", ".ras" => "image/cmu-raster", ".ras" => "image/x-cmu-raster", ".rast" => "image/cmu-raster", ".rexx" => "text/x-script.rexx", ".rf" => "image/vnd.rn-realflash", ".rgb" => "image/x-rgb", ".rm" => "application/vnd.rn-realmedia", ".rm" => "audio/x-pn-realaudio", ".rmi" => "audio/mid", ".rmm" => "audio/x-pn-realaudio", ".rmp" => "audio/x-pn-realaudio", ".rmp" => "audio/x-pn-realaudio-plugin", ".rng" => "application/ringing-tones", ".rng" => "application/vnd.nokia.ringing-tone", ".rnx" => "application/vnd.rn-realplayer", ".roff" => "application/x-troff", ".rp" => "image/vnd.rn-realpix", ".rpm" => "audio/x-pn-realaudio-plugin", ".rt" => "text/richtext", ".rt" => "text/vnd.rn-realtext", ".rtf" => "application/rtf", ".rtf" => "application/x-rtf", ".rtf" => "text/richtext", ".rtx" => "application/rtf", ".rtx" => "text/richtext", ".rv" => "video/vnd.rn-realvideo", ".s" => "text/x-asm", ".s3m" => "audio/s3m", ".saveme" => "application/octet-stream", ".sbk" => "application/x-tbook", ".scm" => "application/x-lotusscreencam", ".scm" => "text/x-script.guile", ".scm" => "text/x-script.scheme", ".scm" => "video/x-scm", ".sdml" => "text/plain", ".sdp" => "application/sdp", ".sdp" => "application/x-sdp", ".sdr" => "application/sounder", ".sea" => "application/sea", ".sea" => "application/x-sea", ".set" => "application/set", ".sgm" => "text/sgml", ".sgm" => "text/x-sgml", ".sgml" => "text/sgml", ".sgml" => "text/x-sgml", ".sh" => "application/x-bsh", ".sh" => "application/x-sh", ".sh" => "application/x-shar", ".sh" => "text/x-script.sh", ".shar" => "application/x-bsh", ".shar" => "application/x-shar", ".shtml" => "text/html", ".shtml" => "text/x-server-parsed-html", ".sid" => "audio/x-psid", ".sit" => "application/x-sit", ".sit" => "application/x-stuffit", ".skd" => "application/x-koan", ".skm" => "application/x-koan", ".skp" => "application/x-koan", ".skt" => "application/x-koan", ".sl" => "application/x-seelogo", ".smi" => "application/smil", ".smil" => "application/smil", ".snd" => "audio/basic", ".snd" => "audio/x-adpcm", ".sol" => "application/solids", ".spc" => "application/x-pkcs7-certificates", ".spc" => "text/x-speech", ".spl" => "application/futuresplash", ".spr" => "application/x-sprite", ".sprite" => "application/x-sprite", ".src" => "application/x-wais-source", ".ssi" => "text/x-server-parsed-html", ".ssm" => "application/streamingmedia", ".sst" => "application/vnd.ms-pki.certstore", ".step" => "application/step", ".stl" => "application/sla", ".stl" => "application/vnd.ms-pki.stl", ".stl" => "application/x-navistyle", ".stp" => "application/step", ".sv4cpio" => "application/x-sv4cpio", ".sv4crc" => "application/x-sv4crc", ".svf" => "image/vnd.dwg", ".svf" => "image/x-dwg", ".svr" => "application/x-world", ".svr" => "x-world/x-svr", ".swf" => "application/x-shockwave-flash", ".t" => "application/x-troff", ".talk" => "text/x-speech", ".tar" => "application/x-tar", ".tbk" => "application/toolbook", ".tbk" => "application/x-tbook", ".tcl" => "application/x-tcl", ".tcl" => "text/x-script.tcl", ".tcsh" => "text/x-script.tcsh", ".tex" => "application/x-tex", ".texi" => "application/x-texinfo", ".texinfo" => "application/x-texinfo", ".text" => "application/plain", ".text" => "text/plain", ".tgz" => "application/gnutar", ".tgz" => "application/x-compressed", ".tif" => "image/tiff", ".tif" => "image/x-tiff", ".tiff" => "image/tiff", ".tiff" => "image/x-tiff", ".tr" => "application/x-troff", ".tsi" => "audio/tsp-audio", ".tsp" => "application/dsptype", ".tsp" => "audio/tsplayer", ".tsv" => "text/tab-separated-values", ".turbot" => "image/florian", ".txt" => "text/plain", ".uil" => "text/x-uil", ".uni" => "text/uri-list", ".unis" => "text/uri-list", ".unv" => "application/i-deas", ".uri" => "text/uri-list", ".uris" => "text/uri-list", ".ustar" => "application/x-ustar", ".ustar" => "multipart/x-ustar", ".uu" => "application/octet-stream", ".uu" => "text/x-uuencode", ".uue" => "text/x-uuencode", ".vcd" => "application/x-cdlink", ".vcs" => "text/x-vcalendar", ".vda" => "application/vda", ".vdo" => "video/vdo", ".vew" => "application/groupwise", ".viv" => "video/vivo", ".viv" => "video/vnd.vivo", ".vivo" => "video/vivo", ".vivo" => "video/vnd.vivo", ".vmd" => "application/vocaltec-media-desc", ".vmf" => "application/vocaltec-media-file", ".voc" => "audio/voc", ".voc" => "audio/x-voc", ".vos" => "video/vosaic", ".vox" => "audio/voxware", ".vqe" => "audio/x-twinvq-plugin", ".vqf" => "audio/x-twinvq", ".vql" => "audio/x-twinvq-plugin", ".vrml" => "application/x-vrml", ".vrml" => "model/vrml", ".vrml" => "x-world/x-vrml", ".vrt" => "x-world/x-vrt", ".vsd" => "application/x-visio", ".vst" => "application/x-visio", ".vsw" => "application/x-visio", ".w60" => "application/wordperfect6.0", ".w61" => "application/wordperfect6.1", ".w6w" => "application/msword", ".wav" => "audio/wav", ".wav" => "audio/x-wav", ".wb1" => "application/x-qpro", ".wbmp" => "image/vnd.wap.wbmp", ".web" => "application/vnd.xara", ".wiz" => "application/msword", ".wk1" => "application/x-123", ".wmf" => "windows/metafile", ".wml" => "text/vnd.wap.wml", ".wmlc" => "application/vnd.wap.wmlc", ".wmls" => "text/vnd.wap.wmlscript", ".wmlsc" => "application/vnd.wap.wmlscriptc", ".word" => "application/msword", ".wp" => "application/wordperfect", ".wp5" => "application/wordperfect", ".wp5" => "application/wordperfect6.0", ".wp6" => "application/wordperfect", ".wpd" => "application/wordperfect", ".wpd" => "application/x-wpwin", ".wq1" => "application/x-lotus", ".wri" => "application/mswrite", ".wri" => "application/x-wri", ".wrl" => "application/x-world", ".wrl" => "model/vrml", ".wrl" => "x-world/x-vrml", ".wrz" => "model/vrml", ".wrz" => "x-world/x-vrml", ".wsc" => "text/scriplet", ".wsrc" => "application/x-wais-source", ".wtk" => "application/x-wintalk", ".xbm" => "image/x-xbitmap", ".xbm" => "image/x-xbm", ".xbm" => "image/xbm", ".xdr" => "video/x-amt-demorun", ".xgz" => "xgl/drawing", ".xif" => "image/vnd.xiff", ".xl" => "application/excel", ".xla" => "application/excel", ".xla" => "application/x-excel", ".xla" => "application/x-msexcel", ".xlb" => "application/excel", ".xlb" => "application/vnd.ms-excel", ".xlb" => "application/x-excel", ".xlc" => "application/excel", ".xlc" => "application/vnd.ms-excel", ".xlc" => "application/x-excel", ".xld" => "application/excel", ".xld" => "application/x-excel", ".xlk" => "application/excel", ".xlk" => "application/x-excel", ".xll" => "application/excel", ".xll" => "application/vnd.ms-excel", ".xll" => "application/x-excel", ".xlm" => "application/excel", ".xlm" => "application/vnd.ms-excel", ".xlm" => "application/x-excel", ".xls" => "application/excel", ".xls" => "application/vnd.ms-excel", ".xls" => "application/x-excel", ".xls" => "application/x-msexcel", ".xlt" => "application/excel", ".xlt" => "application/x-excel", ".xlv" => "application/excel", ".xlv" => "application/x-excel", ".xlw" => "application/excel", ".xlw" => "application/vnd.ms-excel", ".xlw" => "application/x-excel", ".xlw" => "application/x-msexcel", ".xm" => "audio/xm", ".xml" => "application/xml", ".xml" => "text/xml", ".xmz" => "xgl/movie", ".xpix" => "application/x-vnd.ls-xpix", ".xpm" => "image/x-xpixmap", ".xpm" => "image/xpm", ".x-png" => "image/png", ".xsr" => "video/x-amt-showrun", ".xwd" => "image/x-xwd", ".xwd" => "image/x-xwindowdump", ".xyz" => "chemical/x-pdb", ".z" => "application/x-compress", ".z" => "application/x-compressed", ".zip" => "application/x-compressed", ".zip" => "application/x-zip-compressed", ".zip" => "application/zip", ".zip" => "multipart/x-zip", ".zoo" => "application/octet-stream", ".zsh" => "text/x-script.zsh" } In lib/core_extensions.rb - this needs to be required somewhere in your config. class File def self.guess_filetype(filename) `file --mime -b "#{filename}"`.split(";").first || MIME_TYPES_FROM_EXTENSION[File.extname(filename)] end end Finally, in the controller, using your example, in the send_file call, i would do :type=> File.guess_filetype(#uploadedfile.name) The guess_filetype method makes a shell call to file, which is a command line utility. http://en.wikipedia.org/wiki/File_(command) If file can't get the mimetype (it usually does, it's pretty good), then i fall back to my massive list of known mime types from extension, stored in that constant. The reason i do file first, rather than just rely on the list of extensions, is that file looks inside the actual content of the file itself, so if somebody renamed a file's extension, file wouldn't be fooled: it would still know what mime type to return.
I solved this problem by making a slight change on the def file_extension to def file_extension up = Uploadedfile.find(params[:id]) ext = File.extname("#{up.upload_file}") if (ext == ".pdf") "application/pdf" elsif (ext == ".doc") || ( ext == ".rtf") || ( ext == ".docx") "application/vnd.openxmlformats-officedocument.wordprocessingml.document" elsif (ext == ".txt") "text/Plain" elsif (ext == ".rar") "Application/x-rar-compressed" elsif (ext == ".jpeg" || ext==".jpg") "image/jpeg" else "Application/octet-stream" end end I changed this part to ext = File.extname(#uploadedfile.name) to ext = File.extname("#{up.upload_file}") where up = Uploadedfile.find(params[:id])
Ruby on Rails Adobe EchoSign SOAP Request
I am trying to use Ruby on Rails to create a SOAP request to the EchoSign API but I am getting an error saying one of the fields is blank: {http://dto14.api.echosign}RecipientRole: cannot accept '' This is the code I am using: require 'soap/wsdlDriver' require 'base64' filename = 'quote' recipient = 'martin#domain.co.uk' quote_id = params[:id] $S = SOAP::WSDLDriverFactory.new("https://secure.echosign.com/services/EchoSignDocumentService16?wsdl").create_rpc_driver r = $S.sendDocument( :apiKey => 'XXXXXXXXXXX', :senderInfo => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :documentCreationInfo => { :fileInfos => [{ :file => RAILS_ROOT + '/pdfs/' + quote_id + '.pdf', :fileName => filename, }], :recipients => [{ :RecipientInfo => [{ :email => 'martin#domain.co.uk', :fax => SOAP::SOAPNil.new, :role => 'SIGNER' }] }], :message => "This is neat.", :name => "Test from SOAP-Lite: " + filename, :reminderFrequency => "WEEKLY_UNTIL_SIGNED", :signatureFlow => "SENDER_SIGNATURE_NOT_REQUIRED", :signatureType => "ESIGN", :callbackInfo => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :ccs => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :externalId => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :securityOptions => SOAP::SOAPNil.new, # we need to explicitly set elements to nil } ) There must obviously be something wrong with the way I am doing the :recipients => [{ :RecipientInfo => [{ :email => 'martin#domain.co.uk', :fax => SOAP::SOAPNil.new, :role => 'SIGNER' }] }], but I am finding it extremely difficult to find what just from the documentation, I think it will be something silly but can't spot it. update after looking more closely at the example request I tried the following but it made no difference: require 'soap/wsdlDriver' require 'base64' filename = 'quote' quote_id = params[:id] $S = SOAP::WSDLDriverFactory.new("https://secure.echosign.com/services/EchoSignDocumentService16?wsdl").create_rpc_driver r = $S.sendDocument( :apiKey => 'XXXXXXXXXXX', :senderInfo => SOAP::SOAPNil.new, :documentCreationInfo => { :fileInfos => { :FileInfo => { :file => RAILS_ROOT + '/pdfs/' + quote_id + '.pdf', :fileName => filename } }, :recipients => { :RecipientInfo => { :email => 'martin#domain.co.uk', :fax => SOAP::SOAPNil.new, :role => 'SIGNER' } }, :mergeFieldInfo => SOAP::SOAPNil.new, :tos => SOAP::SOAPNil.new, :message => "This is neat.", :name => "Test from SOAP-Lite: " + filename, :reminderFrequency => "WEEKLY_UNTIL_SIGNED", :signatureFlow => "SENDER_SIGNATURE_NOT_REQUIRED", :signatureType => "ESIGN", :callbackInfo => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :ccs => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :externalId => SOAP::SOAPNil.new, # we need to explicitly set elements to nil :securityOptions => SOAP::SOAPNil.new # we need to explicitly set elements to nil } )
Can you please try to pass the value SIGNER with double quotations like "SIGNER". Just like you have for "ESIGN" and some other parameters. Also, if sending for ESIGN, Fax should not need to be nil . Try to not defining :Fax at all.
You should change the email address and the role to have double quotes instead of single quotes. :RecipientInfo => { :email => "martin#domain.co.uk", :fax => SOAP::SOAPNil.new, :role => "SIGNER" change Same as you have done for :reminderFrequency => "WEEKLY_UNTIL_SIGNED", :signatureFlow => "SENDER_SIGNATURE_NOT_REQUIRED",