I recently noticed that on my form, if I try to upload an empty file the page will get redirected to edit instead of create. If I try to upload the file with some text in it, the form will direct to create. I couldn't find any indication that this would happen as I create my object every time (it's never persisted). Is there an explanation behind this?
The code looks something like this:
//controller
def upload
#new_cool_file = CoolFile.new
end
//form in upload.html.erb
<%= form_for #new_cool_file, html: {role: "form"} do |f| %>
<div class="form-group">
<%= f.label :file %>
<%= f.file_field :file %>
</div>
<%= f.submit "Submit"%>
<% end %>
I think you do some wrong in the rails routes.rb file , can you please see tutorial about file upload.
https://richonrails.com/articles/allowing-file-uploads-with-carrierwave
http://railscasts.com/episodes/253-carrierwave-file-uploads
Related
I am trying to get the name of the file uploaded by a user before ActiveStorage goes on to save it. The form is generated using form_with and is shown below:
<%= form_with model: upload do |form| %>
<div class="">
<%= form.file_field :files, multiple: true, direct_upload: true, required: true %>
<%= form.label :files, '', class: 'icon ion-ios-cloud-upload' do %>
<span>click the icon to select files</span>
<% end %>
<div class="actions">
<%= form.submit "Upload", class: "btn btn-primary" %>
</div>
</div>
<% end %>
I have tried accessing params[:upload][files] and calling .original_filename on it as described here but I get the error NoMethodError: undefined method `original_filename' for #<String:0x007fac77fd18c8>.
The file does come back as a string when I inspect the params, so how do I get the filename or how do I get original_filename to work?
I was finally able to get the file name by doing file.blob.filename after the file had been attached.
Based on the ActiveStorage documentation, I found this worked for me:
file.filename.to_s
In my case I have a model with
has_one_attached :file
OP's situation is slightly different and your situation may differ too, so adjust accordingly.
Troy's solution did not work for me as-is. I had to add the .to_s to get the file name instead of an ActiveStorage::Filename object. But I'm not sure why he's using .blob in there. I didn't need it, but perhaps there's a good reason.
You need to add multipart: true to your form.
https://guides.rubyonrails.org/form_helpers.html#uploading-files
The other thing is that if you have multiple files you'll have multiple filenames.
params[:upload][files].each do |file|
file.original_filename
end
Just running
rake assets:precompile
worked for me.
This is the code in _image_fields.html.erb
<div class="nested-fields">
<div class="image-fields"> <%= image_tag f.object.image_url(:thumb) if f.object.image_url.present? %>
<%= f.file_field :image %>
<%= f.hidden_field :image_cache %> </div> <div class="add-language-spacing"> <%= link_to_remove_association 'Remove Image', f, id: 'remove_photo' %> </div>
This is where i'm rendering that partial in _profile_form.html.erb
<p id="tag">Add Some Photos!</p>
<div>
<%= f.fields_for :images do |image| %>
<%= render "image_fields", f: image %>
<% end %>
</div>
And then finally, in profile/edit.html.erb
<div class="profile-form">
<h1 class="page-title">Update Profile</h1>
<%= render 'profile_form' %>
</div>
My uploader looks like this
# Create different versions of your uploaded files:
process resize_to_fit: [300,300]
version :thumb do
process resize_to_fill: [200,200]
end
The thumb version only shows up after I press update profile and then refresh the page. For whatever reason it won't show the thumbnail version when I press choose file.
This is the confusing part of webdevelopment when you are starting out: what is executed in the client (browser) and what is executed on the server.
1) You are using cocoon to build a form, this means all data inside the form is only processed on the server once you submit the form.
2) You are using carrierwave, which explicitly only works in ruby on the server.
So together this means: only after submitting the form to the server, your uploader will create the thumbnail, and thus only after submitting the image_url will be defined.
What you want is, once you select the image, it will show a thumbnail, before uploading it to the server, and this means you either need
ajax to immediately post to the server (and let it render the thumbnail)
a javascript solution, which will read the contents of the file and show it (client-side, in the browser), before sending it to the server
Personally I do not believe cocoon is the right tool for the job here. I would suggest using something like
jquery-file-upload
dropzonejs
With Cloudinary and their Carrierwave plugin I can write a form in my view that will upload an image to their cloud and bind it to a model attribute called picture, like so:
<%= form_for(#post) do |post_form| %>
<%= post_form.hidden_field(:picture_cache) %>
<%= post_form.file_field(:picture) %>
<% end %>
This works. But I can't figure out how to bind the attribute to the model while following their documentation for direct uploads in Rails. Their example uses a form_tag that isn't bound to a model:
<%= form_tag(some_path, :method => :post) do %>
<%= cl_image_upload_tag(:image_id) %>
...
<%= end %>
I'm looking for some example that's like <%= post_form.some_upload_method(:picture) %>. Any chance someone else has done this for direct uploads for their models and knows what I'm looking for?
You can use the following syntax:
<%= post_form.cl_image_upload(:picture) %>
I'm using CarrierWave and Nested Form Gem. Using the section titled 'Making uploads work across form redisplays' on the Carrierwave github page(https://github.com/jnicklas/carrierwave) I'm able to successfully store the cache so that even if the user makes a mistake then the file is saved. The first time I hit the page and click "Upload File" it works and shows the name of the file as well as a small thumbnail icon indicating the type of file that has been uploaded.
However the file input button is blank upon a redisplay and the icon is gone. However I know it's there because if I submit again with valid information and leave the file input button alone it creates a new resource. Here's a snippet of my code.
<%= nested_form_for #resource, :html=>{:multipart => true } do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<%= f.fields_for :attachments do |attachment_form| %>
<p>
<%= attachment_form.label :file %>
<% if !attachment_form.object.file.path.blank? %>
<% file_info = get_cache_file_info attachment_form.object.file.path %>
<%= image_tag(File.join('/tmp/cache/', file_info[:folder])) #THIS DISPLAY CORRECTLY %>
<% end %>
<%= attachment_form.file_field :file %>
<%= attachment_form.hidden_field :file_cache %>
</p>
<%= attachment_form.link_to_remove "Remove this attachment" %>
<% end %>
<%= f.link_to_add "Add attachment", :attachments %>
<p><%= f.submit %></p>
<% end %>
I'm wondering if I have to edit the HTML file input to display the icon or is there some other Rails Way to take care of this. Also the image_tag display correctly, but for my application having users upload text files so the images aren't very helpful.
Thanks in advance!
Update
I also tried setting the value of the 'input' tag like so:
<%= attachment_form.file_field :file, :value => "#{File.join(file_info[:folder], '/',attachment_form.object.file.identifier)}" %>
and that didn't work either. The value of the 'input' tag is set correctly, but it still shows up as "No file selected"
The CarrierWave introduction doesn't make this very clear, but it sounds like your code is functioning 'correctly'. The cache field just serves to ensure that your attachment will be saved after a valid submission.
This document explains that the file input element's FileList should be read only, presumably for security reasons.
I have CarrierWave (0.6.1) and Nested Form gem installed. I have a Resource model with many Attachments which have a FileUploader.
I have a nested form where users can upload multiple files with one resource. I am following the section on github (https://github.com/jnicklas/carrierwave) that says how to make uploads work across redisplays unfortunately it's only for 1:1 ratio.
Here's the code that I have:
<%= nested_form_for #resource, :html=>{:multipart => true } do |f| %>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<%= f.fields_for :attachments, #attachment do |attachment_form| %>
<p>
<%= attachment_form.label :file %>
<%= attachment_form.file_field :file %>
<%= attachment_form.hidden_field :file_cache %>
<%= image_tag(attachment_form.file_url) if attachment_form.file? # DOESN'T WORK!!! %>
</p>
<%= attachment_form.link_to_remove "Remove this attachment" %>
<% end %>
<%= f.link_to_add "Add attachment", :attachments %>
<p><%= f.submit %></p>
<% end %>
Everything works and it populates the file_cache variable just fine for the attachment_form however I somehow need to add the following line in there to show the user the image of the document:
<%= image_tag(attachment_form.file_url) if attachment_form.file? %>
However there's a number of problems with this. First of all attachment_form is referencing the form_builder whereas I want the actual attachment. Second, attachment knows nothing about file.
Probably need to use another type of looping mechanism, but I'm new to Ruby so any help is appreciated.
Thanks all!
If you try this:
<%= image_tag(attachment_form.object.file_url) if attachment_form.object.file? %>
You will be able to show previous uploaded images. But if you want to display uploaded right now, you need to use something else. For example: https://github.com/blueimp/jQuery-File-Upload/wiki/jQuery-File-Upload-v4-for-Rails-3
Sorry, if I misunderstood your question.