Uploading model attributes with file using AWS SDK Rails 4 - ruby-on-rails

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)

Related

How do I get the binary data of an uploaded image in Rails 5?

I'm using Rails 5 and the ruby-filemagic gem. How do I get the binary data from an uploaded file? My form looks like this
<%= form_for #person, html: { multipart: true } do |f| %>
...
<div class="field">
<%= f.label :image %><br>
<%= f.file_field :image %>
</div>
and my controller is as follows
def create
#person = Person.new(person_params)
if #person.image
cur_time_in_ms = DateTime.now.strftime('%Q')
file_location = "/tmp/file#{cur_time_in_ms}.ext"
File.binwrite(file_location, #person.image.tempfile)
fm = FileMagic.new(FileMagic::MAGIC_MIME)
#person.content_type = fm.file(file_location, true)
end
if #person.save
redirect_to #person
else
# This line overrides the default rendering behavior, which
# would have been to render the "create" view.
render "new"
end
end
but when I look at the content of my file (the one I have copied into the "/tmp" directory), it shows ...
#<ActionDispatch::Http::UploadedFile:0x007fba2573bbd0>
How do I get just the binary data (preferably in the "#person.image" attribute)?
hitting p #person.image.methods should yield what you're looking for (I'm guessing #read)

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?

Rails - Upload and parse multiple CSV files

Im trying to upload and parse multiple CSV files. What I have so far:
My View
<h3>Upload multiple files</h3>
<%= form_tag({:controller => "multi_uploader", :action => "import"}, :multipart => true) do %>
<em>Upload a tab-separated .txt file to generate new rating sets.</em> <hr/>
<%= file_field_tag :file_1 %>
<hr/>
<%= file_field_tag :file_2 %>
<hr/>
<%= file_field_tag :file_3 %>
<hr/>
<%= file_field_tag :file_4 %>
<hr/>
<%= file_field_tag :file_5 %>
<hr/>
<%= file_field_tag :file_6 %>
<hr/>
<%= submit_tag "Import Data", :class => "btn btn-link"%>
<% end %>
My Controller:
def import
unless params[:file_1].nil?
file_1 = params[:file_1]
RatingSet.multi_uploader(file_1)
end
unless params[:file_2].nil?
file_2 = params[:file_2]
RatingSet.multi_uploader(file_2)
end
unless params[:file_3].nil?
file_3 = params[:file_3]
RatingSet.multi_uploader(file_3)
end
unless params[:file_4].nil?
file_4 = params[:file_4]
RatingSet.multi_uploader(file_4)
end
unless params[:file_5].nil?
file_5 = params[:file_5]
RatingSet.multi_uploader(file_5)
end
unless params[:file_6].nil?
file_6 = params[:file_6]
RatingSet.multi_uploader(file_6)
end
redirect_to "/multi_uploader", :flash => { :notice => "Successfully Uploaded." }
end
My Model method to import file:
def self.multi_uploader(file)
upload = File.open(file.path)
#Parse file and save data to db.
end
In my multi_uploader method, I parse out a key (from the file) for which category the file is supposed to be uploaded to. Everything works as expected when I upload a single file, however if I upload multiple files, the contents of all files are being saved for to a single category, rather than multiple categories. Its as if all files are being treated as a single file, rather than n individual files. What can I change to upload each file individually?
Well, as far as I see. This behavior shouldn't actually be happening. I would suggest another way of doing this code, since it's looking a bit polluted.
def import
(1..x).each do |i| #with x being the max number of files uploaded at the same time
RatingSet.multi_uploader(params["file_#{i}".to_sym])
end
redirect_to "/multi_uploader", :flash => { :notice => "Successfully Uploaded." }
end
Either way, this shouldn't solve your problem. I can't tell why this is happening to be honest.
UPDATE:
Have you considered using: <%= f.file_field :file, :multiple => true %> instead of mutiple file_tags?

Form to submit file to controller upload action in 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

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

Resources