Search code examples
ruby-on-railsfile-uploadwistia

Passing form_tag variable to controller + API


I've been fighting with this issue for 2 days but can't overcome following step.

I am trying to use Wistia API to upload a video, but got stuck on the moment of passing the filename and data from view to controller.

I am using official http://wistia.com/doc/upload-api#examples_using_ruby API documentation but keep getting "no implicit conversion of Symbol into String" error.

I would really appreciate any help or hints with this.

My view index.html.erb:

<h1>File Upload</h1>
<%= form_tag('/uploads', method: :post, multipart: true) do %>

<%= file_field 'pic', 'data' %></p>
<%= submit_tag "Upload" %>
<%= debug params %>
<% end %>

My controller Uploads controller:

class UploadsController < ApplicationController
  def home
  end

  def uploadFile
  end

  def create
    @xyz = post_video_to_wistia(:pic, :data)
  end


  require 'net/http'
  require 'net/http/post/multipart'

    def post_video_to_wistia(name, path_to_video)
  uri = URI('https://upload.wistia.com/')

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  # Construct the request.
  request = Net::HTTP::Post::Multipart.new uri.request_uri, {
    'api_password' => '<API_PASSWORD>',
    'contact_id'   => '<CONTACT_ID>', # Optional.
    'project_id'   => '<PROJECT_ID>', # Optional.
    'name'         => '<MEDIA_NAME>', # Optional.

    'file' => UploadIO.new(
                File.open(path_to_video),
                'application/octet-stream',
                File.basename(path_to_video)
              )
  }

  # Make it so!
  response = http.request(request)

  return response
end

end

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"/dRprM7ZjQzzb9N9OErk0Dy4tSt/+zsUldpOed8jCqY=",
 "pic"=>{"data"=>#<ActionDispatch::Http::UploadedFile:0x3ef23e0 @tempfile=#<Tempfile:C:/Users/Maciek/AppData/Local/Temp/RackMultipart20140527-7076-bo3tzy>,
 @original_filename="example.jpg",
 @content_type="image/jpeg",
 @headers="Content-Disposition: form-data; name=\"pic[data]\"; filename=\"example.jpg\"\r\nContent-Type: image/jpeg\r\n">},
 "commit"=>"Upload"}

Solution

  • Update create action as below:

    def create
      @xyz = post_video_to_wistia(:pic, params[:pic][:data]) ## Notice params[:pic][:data]
    end
    

    Note:

    params[:pic][:data] contains the path_to_video entered and submitted via the form.

    Currently, you are invoking post_video_to_wistia method with second argument as :data(which is a symbol) i.e., you receive parameter path_to_video = :data in the invoked method.

    You must be receiving the error on line

    'file' => UploadIO.new(
                File.open(path_to_video), ## <== Problem here
                'application/octet-stream',
                File.basename(path_to_video)
              )
    

    As, instead of passing actual path of the video, a symbol was passed in File.open(path_to_video) which is causing the error as

    no implicit conversion of Symbol into String
    

    Ruby can't convert :data to a path_to_video(eg: /path/to/myvideo).

    As suggested above, you need to pass params[:pic][:data] as second argument to post_video_to_wistia method for your code to work.

    UPDATE:

    For the error in comment

    I've followed your guidance but now getting "no implicit conversion of ActionDispatch::Http::UploadedFile into String"

    what you need to do is, update the following code

    'file' => UploadIO.new(
                File.open(path_to_video),
                'application/octet-stream',
                File.basename(path_to_video)
              )
    

    With

    'file' => UploadIO.new(
                path_to_video.tempfile,  ## <== Changed this
                'application/octet-stream',
                path_to_video.original_filename ## <== Changed this
              )
    

    This change is due to the fact that you are already receiving a file in path_to_video(which is an instance of ActionDispatch::Http::UploadedFile class) and you can access the file via path_to_video.tempfile and get the uploaded filename via path_to_video.original_filename