Form to submit file to controller upload action in rails - ruby-on-rails

Controller:
class SongsController < ApplicationController
.
.
.
def upload
bucket = find_bucket
file = params[:file] edit: previously was file = :file
if bucket
AWS::S3::S3Object.store(file, open(file), bucket)
redirect_to root_path
else
render text: "Couldn't upload"
end
end
private
.
.
.
def find_bucket
AWS::S3::Bucket.find('kanesmusic')
end
end
Upload form in index view:
<h2>Upload a new MP3:</h2>
<%= form_tag upload_path, :method => "post", :multipart => true do %>
<%= file_field_tag :file %>
<%= submit_tag "Upload" %>
<% end %>
Error (edited):
TypeError in SongsController#upload...can't convert AWS::S3::Bucket into String
I'm trying to create this form that can select a file from a users hard drive and upload it.

You need to use params. That where all the vars are stored.
Like so:
params[:file]
But for using file upload (thats slightly different) have a look at the docs
http://guides.rubyonrails.org/form_helpers.html#uploading-files

Related

Uploading model attributes with file using AWS SDK Rails 4

What I'm looking to do is save my Song model attributes in the same form that I use to upload my mp3 files. I'm currently using the AWS-SDK gem.
As of now, I can successfully upload mp3 files to AWS. However, when I attempt to save the "song_title" and "album_id" attributes as well, the data does not save, but the file is uploaded.
Song attributes:
"id", "url", "name", "created_at", "updated_at", "album_id", "song_title"
songs_controller:
class Albums::SongsController < ApplicationController
before_filter :set_user_friendships
def new
#song = Song.new
end
def create
# Make an object in your bucket for your song
obj = S3_BUCKET.objects[params[:file].original_filename]
# Upload the file
obj.write(
file: params[:file],
acl: :public_read
)
# Create an object for the song
#song = Song.new(
url: obj.public_url,
name: obj.key
)
# Save the upload
if #song.save
redirect_to songs_path, success: 'File successfully uploaded'
else
flash.now[:notice] = 'There was an error'
render :new
end
end
def index
#user_friendships = current_user.user_friendships.all
#songs = Song.all
end
def song_params
params.require(:song).permit(:id, :url, :name, :song_title, :album_id)
end
def set_user_friendships
#user_friendships = current_user.user_friendships.all #this is here because of partial UGHHH
end
end
songs/_upload_song.html.erb:
<p>Upload a song</p>
<%= form_tag songs_path, enctype: 'multipart/form-data' do %>
<%= file_field_tag :file %>
<%= submit_tag 'Upload song' %>
<% end %>
I tried changing the create method within the songs_controller to the following. (I added "song_params"):
def create
# Make an object in your bucket for your song
obj = S3_BUCKET.objects[params[:file].original_filename]
# Upload the file
obj.write(
file: params[:file],
acl: :public_read
)
# Create an object for the song
#song = Song.new(song_params,
url: obj.public_url,
name: obj.key
)
# Save the upload
if #song.save
redirect_to songs_path, success: 'File successfully uploaded'
else
flash.now[:notice] = 'There was an error'
render :new
end
end
and the songs upload form to the following:
<p>Upload a song</p>
<%= form_tag songs_path, enctype: 'multipart/form-data' do %>
<%= file_field_tag :file %>
<%= text_field_tag :song_title %>
<%= submit_tag 'Upload song' %>
<% end %>
However, I get the following error:
param is missing or the value is empty: song
I suspect that the issue has something to do with the "form_tag" vs the "form_for" difference in forms.
After taking a look around, I found that the form_tag creates a basic form, and form_for creates a form for a model object.
So when changing the upload form to the one below:
<%= form_for Song.new, enctype: 'multipart/form-data' do |f| %>
<%= f.label :file %>
<%= f.file_field :file %>
<%= f.label :song_title %>
<%= f.text_field :song_title %>
<%= f.label :album_id %>
<%= f.number_field :album_id %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
I get the following error:
undefined method `original_filename' for nil:NilClass
And the error references the following lines within the "create" method of my songs_controller:
obj = S3_BUCKET.objects[params[:file].original_filename]
I looked through the AWS-SDK documentation, but I find this information surprisingly hard to find.
Would someone mind shedding some light on how I would go about saving my Song attributes as well as uploading my Song mp3 file?
You created the method song_params, but I do not see you using it. You must explicitly set your object with the params returned by song_params in order to save the attributes upon song.save.
#song = Song.new(song_params)

Rails let user upload photo with carrierwave

I have entity Lead. I want to be able to upload a picture and save its path to status_photo field. I use carrierwave gem for photo uploads.
In my model I've mounted mount_uploader :status_photo, PhotoUploader (My photouploader definitely works so the problem with code in my controller or view)
Right now I have a form for editing my lead.
<%= form_for(#lead) do |f| %>
phone: <%= #lead.phone %>
.
.
.
status: <%= select_tag(:status, options_for_select([['0', 0], ['1', 1]], selected: #lead.status )) %>
photo of car repair process:
<%= f.file_field :status_photo %><br/>
<%= f.submit "Save changes" %>
<% end %>
In my controller I have:
def update
#lead = Lead.find(params[:id])
if #lead.update_attributes(status: params[:status], status_photo: params[:status_photo] )
flash[:success] = "Information updated"
redirect_to leads_url
else
render 'edit'
end
end
As you can see I also update status field which is updated fine but status_photo doesn't. What do I do?

How to append user_id to Rails file upload?

I'm building an app where users can upload csv files to load data onto our platform. I have a form that lets a user upload a file and a method that saves the file in a specified folder. I want to append the user_id to the filename. How would I do that?
my form:
<%= form_tag import_listings_path, multipart: true do %>
<%= file_field_tag :my_file %>
<%= hidden_field_tag :user_id, current_user.id %>
<%= submit_tag "Import CSV" %>
<% end %>
my controller method:
def import
tmp = params[:my_file].tempfile
file = File.join("public", params[:my_file].original_filename)
FileUtils.cp tmp.path, file
end
For example, if a user uploads test.csv and their user_id is 20. I want the new filename to be test20.csv
A bit ugly but this should do the job... basically extracting the file extension (obtaining the last string after the '.'), appending the user id and adding the extension back:
x = params[:my_file].original_filename.split('.')
x[x.length - 2] += params[:user_id]
file = File.join("public", x.join('.'))

why is form_ tag code is not working in ruby mine 5.4.3.2.1?

I am building an ROR application in ruby mine .But the following doesn't seems to run `
<%= form_tag upload_index_path({:action => 'uploadFile'},
:multipart => true) do %>
<p><label for="upload_file">Select File</label> :
<%= file_field 'upload', 'datafile' %></p>
<%= submit_tag "Upload" %>
<% end %>`
This code is in my view file. I am trying to build a site where i can upload files. Everything appears good but when i click the upload button the file doesn't get uploaded only the url changes. Why is that??
This is my controller code
class UploadController < ApplicationController
def index
render :file => 'app\views\upload\uploadfile.html.erb'
end
def uploadFile
post = DataFile.save(params[:upload])
render :text => "File has been uploaded successfully"
end
end
This is my model code
class DataFile < ActiveRecord::Base
# attr_accessible :title, :body
def self.save(upload)
name = upload['datafile'].original_filename
directory = "public/data"
# create the file path
path = File.join(directory, name)
# write the file
File.open(path, "wb") { |f| f.write(upload['datafile'].read) }
end
end
I have not been able to find solution. I have been trying for a week.
In your form_tag declaration, remove the multipart from the path options as follows:
<%= form_tag upload_index_path({:action => 'uploadFile'}) , :multipart => true do %>
<p>
<label for="upload_file">Select File</label> :
<%= file_field 'upload', 'datafile' %>
</p>
<%= submit_tag "Upload" %>
<% end %>
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag

File Upload By form_tag form on Ruby on Rails

I'd like to make a simple file uploader using tag_form on Rails 3.2.8.
But when I try to submit a image file, I get an error saying
Error Message (when I try to submit a image file)
NoMethodError in CoursesController#attachment
undefined method `original_filename' for "2012-03-02 21.53.55.jpg":String
----- BEGIN P.S.(20121216 19:32) -----
or
Error Message (when I added ":multipart => true" on show.html.erb)
Encoding::UndefinedConversionError in CoursesController#attachment
"\xFF" from ASCII-8BIT to UTF-8
----- END P.S. -----
It seems that the program consider the file as String?
There might be some problem in the view file.
I'd appreciate it if you help me with this problem. Here's my codes.
app/view/show.html.erb
<%= form_tag(attachment_course_path, :action=>'attachment') do %>
<div class="field">
<%= label_tag :file %>
<%= file_field_tag :file %>
</div>
<div class="actions">
<%= submit_tag 'Submit' %>
</div>
<% end %>
app/controller/courses_controller.rb
def attachment
t = Time.now.strftime("%Y%m%d%H%M%S")
uploaded_io = params[:file]
File.open(Rails.root.join('public', 'upload', uploaded_io.original_filename), 'w') do |file|
file.write(uploaded_io.read)
end
end
config/routes.rb
resources :courses, :only => [ :show ] do
member do
post :attachment
end
end
seems the form is not sending files with request. you need to set :multipart => true in form_tag.
The problem seems similar to RoR upload Undefined encoding conversion
After setting :multipart => true in form_tag you need to open the file in binary mode ('wb' instead of 'w'):
app/controller/courses_controller.rb
...
File.open(Rails.root.join('public', 'upload', uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
end
...

Resources