I have a rails app with a model, products that has a nested model, productdocuments. I'm using Carrierwave to upload PDFs, Word Docs, etc .. as the documents.
In my edit.html.erb I have my form field rendering in a partial;
<%= f.file_field :resource, name: "product[productdocuments_attributes][][resource]", multiple: true, :placeholder => "Resource", id: "product_productdocuments_attributes" %>
And an array of the uploaded docs in a partial:
<%= render #product.productdocuments %>
The issue I'm seeing is that when I upload a file, rails is triggering a render of update.js.erb on the Product NOT the create.js.erb from productdocument This makes it harder to append the partial with the new productdocument.
Any idea how to to trigger create.js.erb from Productdocuments?
I guess in the edit.html.erb there's something like:
<%= form_for #product, remote: true do |f| %>
<%= f.file_field :resource, name: "product[productdocuments_attributes][][resource]", multiple: true, :placeholder => "Resource", id: "product_productdocuments_attributes" %>
<%= f.submit %>
<% end %>
which on submit sends request to the ProductsController, not to ProductDocumentsController as you expect. Since #product is a persisted record, the request goes to update method.
In this case, an additional form for product documents is going solve the problem:
<%= form_for #product.productdocuments.build, remote: true do |f| %>
<%= f.file_field :resource, , multiple: true, :placeholder => "Resource" %>
<%= f.submit %>
<% end %>
#product.productdocuments.build builds a new object, therefore request is going to create method.
Hope it helps.
Related
I am using active storage to implement file uploads in a form.
<%= form_for #listing do |form| %>
# ...
<%= form.text_field :title, placeholder: "Title" %>
<%= form.file_field :image, direct_upload: true, accept: "image/png,image/gif,image/jpeg" %>
# ...
<% end %>
I handle the form submission in the controller like so:
def create
#listing = Listing.new(safe_params)
if #listing.save
flash[:success] = "Your posting has been submitted"
redirect_to root_url
else
flash.now[:warning] = #listing.errors.full_messages
render 'new'
end
end
If validations fail, the new page is re-rendered. If I've already entered a title, the previously entered title is present in the re-rendered form. However, if I've already selected a file, that file is not selected in the re-rendered form.
I select a file:
On submission, the file is uploaded but validation fails and the page is re-rendered. The file is no longer selected:
I'm not quite sure what's going on here. Why isn't the file remembered when the new page is re-rendered? Why doesn't the form display the selected file? What do I need to do to ensure it's still selected when the page re-renders?
You could try something like this:
<%= form_for #listing do |form| %>
# ...
<%= form.text_field :title, placeholder: "Title" %>
<%= form.hidden_field :image, value: form.object.image.signed_id if form.object.image.attached? %>
<%= form.file_field :image, direct_upload: true, accept: "image/png,image/gif,image/jpeg" %>
# ...
<% end %>
This is a common issue with browser
you can think it as -
File field as a one-way field. Browser to server, but not server to
browser.
That's not how a file field works in any browser.
So on edit page you would have to explicitly preview file or file name at any other place just to let user know that there is already a file present unless he want to update that with another file.
<%= form_for #listing do |form| %>
#...
<div>
<%if form.object.image.present?%>
#name of file
<%end%>
</div>
<%= form.file_field :image, direct_upload: true, accept: "image/png,image/gif,image/jpeg" %>
#..
<%end%>
I'm playing with ActiveStorage and trying to upload some files locally. Everything works great with the code below, but only if I remove multiple: true from the form. When it is on the form, I get an unpermitted param "files" error in the console. The unpermitted param comes from the way the form is submitting the hash.
Without multiple: true the hash lists attachments as an array (this is the working version):
"article"=>{"files"=>[#<ActionDispatch::Http::UploadedFile:0x007fb4e8e287f0
But with it turned on it it removes the array:
"article"=>{"files"=>#<ActionDispatch::Http::UploadedFile:0x007fb4eb07b7d0
What is causing this form behavior and how can I fix it?
I got the code sample from Engine Yard and here is the project code:
<h3>Attach files to this post</h3>
<%= form_with model: #article, local: true do |f| %>
<div class="form-row">
<%= f.label :file_upload, 'Attach a file' %>
<%= f.file_field :files, multiple: true %>
</div>
<%= f.submit %>
<% end %>
<h3>Attached files</h3>
<% #article.files.each do |file| %>
<%= link_to file.blob.filename, url_for(file) %>
<% end %>
When you use multiple: true you need to permit an array explicit in the article_params for :files:
For example:
params.require(:article).permit(:author, :text, files: [])
You can read more under Action Controller
Good luck!
I came across file uploading problem in Rails. I found file_field :file helper, that can be used with form_for(#some_model). However, I cannot find any usage for this case, as those tags are used to create/edit some model, by mass assigning. There is, AFAIK, no possibility to treat fileupload as typical field ( See File upload won't work in Ruby on Rails 3 using Multipart Form ). In such a case, manual operation on uploaded file is required. So, why would someone even want to puts a fileupload as a part of model editing?
photo.rb
class Photo < ActiveRecord::Base
attr_accessible :name, :filename,
end
photo_form.html.erb
<%= form_for(#photo, :multipart => true) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.file_field :file %>
<%= f.submit %>
<% end %>
photos_controller.rb
def create
#photo = Photo.new(params[:photo])
line above fails, because theres no :file attribute. It must be handled before and manually removed from :params. Once more - is there any real usage for such tags?
I will will you an example how I am using it I think it explains itself good enough, I hope this helps
<%= form_for #item do |f|%>
<%= f.file_field :photo, accept: 'image/png,image/jpeg'%>
<% end %>
Let me know if you have any doubts
I remember that I used this to upload a xml file in Rails
view:
<%= form_tag({action: :upload}, multipart: true) do %>
<%= file_field_tag 'xml_file' %>
<%= submit_tag 'Submit' %>
<% end %>
controller:
def upload
file_data = params[:xml_file]
end
It is using form_tag but it would not be hard to add other info into that form also.
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.
I've got two gems that i use and enjoy
gem 'activeadmin'
and
gem "ckeditor"
I'd like for my 'content' field to use ckeditor.
In my past apps, I render ckeditor in a form like this:
<%= form_for #resource do |f| %>
<div class="field">
<%= f.label :content %>
<br />
<%= cktext_area_tag("page_part[content]", #page_part.content) %>
</div>
...
<% end %>
Now i just added activeadmin to my stack and like what i see so far. So, I read that you can customize the form like so by editing the app/admin/#{resource}.rb file:
ActiveAdmin.register NewsItem do
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "NewsItem", :multipart => true do
f.input :title
f.input :content
f.input :photo
#NOT WORKING
cktext_area_tag("news_item[content]", #news_item.content)
#NOT WORKING
end
f.buttons
end
end
How can i get this form helper to work in active_admin, and what would i put in place of #news_item.content. #news_item is null... So right now I'm a bit confused.
When I try even witout reference to #news_item like so:
cktext_area_tag("news_item[content]", 'i cant be edited properly')
I still get:
undefined method `cktext_area_tag' for #<ActiveAdmin::DSL:0x00000007e02250>
Any help would be appreciated!
Ok,
Answer was pretty simple.
Taken from active admin's own documentation page: http://activeadmin.info/docs/5-forms.html
ActiveAdmin.register Post do
form :partial => "form"
end
Then I was able to use any form helper tags I wanted to:
<%= javascript_include_tag "/javascripts/ckeditor/ckeditor.js" %>
<%= semantic_form_for [:admin, #news_item], :multipart => true do |f| %>
<%= f.inputs :title, :photo %>
<%= cktext_area_tag("news_item[content]", #news_item.content) %>
<% end %>
You can try
f.template.some_view_method