Ruby on Rails AJAX file upload - ruby-on-rails

Is there any easy way how to handle AJAX file upload in Rails? e.g. with a plugin

If you're using Rails 3, I've written a plugin that makes AJAX style file uploads relatively trivial to implement.
http://rubygems.org/gems/remotipart

JQuery File Upload is very active and versatile file upload widget project.
See the demo here: http://blueimp.github.com/jQuery-File-Upload/
Here's a Gem: http://rubygems.org/gems/jquery.fileupload-rails
The wiki also has Rails examples: https://github.com/blueimp/jQuery-File-Upload/wiki

It's not really necessary to use some special plugins for that.
Easiest way to do ajax picture upload for me was just make form that uploading pictures to act like ajax. For that I use ajaxForm jQuery plugin: http://www.malsup.com/jquery/form/
Than return to js uploaded picture and put it to your page.
So, you should make your form be ajaxForm:
$('#uploader').ajaxForm({dataType: "script",
success: ajaxFormErrorHandler,
error: ajaxFormSuccessHandler
}
controler looks like that:
def add_photo
#photo = PhotosMeasurement.new(params[:user_photo])
respond_to do |format|
if #photo.save
format.json { render :json => #photo}
else
format.json { render :json => nil}
end
end
end
and in ajaxFormSuccessHandler you simply get picture object:
var photo = jQuery.parseJSON(responseText.responseText);
and put photo wherever you like:
target.find('.addPhoto').before(''+
'<input class="imageId" type="hidden" value='+photo.id+' > '+
'<img src='+photo.photo.thumb.url+' alt="Thumb_1"> ');
P.S: Don't really know why but if you return to ajaxForm handler something, it handle that request as ERROR not SUCCESS.
P.P.S: surely jQuery-File-Upload plugin makes more but if you don't need all that, you can use this way.
P.P.P.S: you should have already functional non-ajax file upload for do that =)

You can use Jquery Form
download jquery.form.min.js and put it to vendor/assets/javascripts folder
in your application.js
//= require jquery.form
in your view (haml sample):
= form_for user, authenticity_token: true, :multipart => true, id: 'user_form' do |f|
= f.label :avatar, t("user.avatar")
= f.file_field :avatar, accept: 'image/png,image/gif,image/jpeg'
= f.submit t(user.new_record? ? 'add' : 'update'),
class: 'btn btn-primary', data: {disable_with: t(user.new_record? ? 'adding' : 'updating')}
:javascript
$('#user_form').ajaxForm()
here is Rails app sample https://github.com/serghei-topor/ajax-file-upload-rails-sample

Related

Upload file to server is going through normal request, while ajax is not working Ruby on Rails

i am currently trying to upload a file with an ajax request on rails. My controller code is (main action):
def changePage
#welcome = WelcomeController.new
respond_to do |format|
format.html
format.js
end
end
My application is single paged, and the pages are changed via ajax requests and everything is working (but i am doint it with link_to, while in this case i use form_for - i do not know if this can be the cause). So in the view (changePage.html.index) i am rendering a partial view (_main.html.slim) which has the following code:
= form_for(:uploaded_file, :remote => true, :url => {:action => 'changePage'}, :html =>
{:multipart=>true}, :authenticity_token => true) do |f|
div class="browse"
span
| Choose file..
= f.file_field :uploaded_file
div id="file-status"
| You have not selected any files yet.
= f.submit :value => "Upload"
So when the Upload button is triggered i end up with a normal request to the server, and not an ajax request (i have changePage.js.erb file). So if someone has some idea about why this is happening it would be nice. {:
Thanks in advance!
For ajax upload you can use gem remotipart.
I am using a javascript plugin File-Uploader . It's simple and works well . I hope it would help you ^_^
You cannot just upload file with an AJAX request, it's technically impossible. So, your options are:
Use normal upload with full page request to keep it simple.
Use ugly hacks e.g. hidden iframe to achieve AJAX-like upload.
Use third-party uploader (there are plenty of them).
I suggest either option #1 or #3, depending on your requirements. #1 if you just need a simple upload, #3 if you need advanced features e.g. multiple files upload, drag & drop upload, chunked upload (for large files) etc.

Rails with jQuery + AJAX fundamentals

I've been given a task to do a simple Task Manager on Ruby On Rails. It's pretty simple for me but there is one issue. Everything has to be "ajaxified" and data should be passed around in JSON.
How I do this right now.
On index.html.erb
I'm creating a simple form with these parameters:
<%= form_for(Task.new, remote: true, :html => {:'data-type' => 'json'}) do |f| %>
In TasksController:
class TasksController < ApplicationController
respond_to :json
def create
#project = Project.find(params[:task][:project_id])
if #task = #project.tasks.create!(name: params[:task][:name], description: params[:task][:description])
respond_with(#task)
else
flash[:error] = 'error'
end
and inside on index.htm.erb I have:
$(document).ready(function(){
$("#new_task").bind('ajax:success', function(evt, data, status, xhr){
var row = ('<tr id="task.id"><td>'+data.name+'</td>'+'<td>'+data.description+'</td>'+'<td>'+data.state+'</td>'+'<td><%= link_to "delete task", task_path(task.id), :method => "delete", remote:true, data: { confirm: "Are you sure?" } %></td></tr>');
$(row).insertAfter("#tasks_table tr:first");
slicer($("#total"));
slicer($("#active"));
}); });
$("#new_task").bind("ajax:beforeSend", function(event,xhr,status){
$(this)[0].reset();
});
And now I'd like to give some explanation about how this might work(my personal thoughts)
by specyfing remote: true, I'm telling the form to submit data in input on server via Unobtrusive Javascript, rails 3 feature. It sends an usual hash in my example this is params[:task][:name] etc, but it expects to get back JSON because I did set :html => {:'data-type' => 'json'}) (is this correct syntax?). Now in my TasksController class I have the respond_to :json, it means that controller WILL answer those requests, where data-type json is specified, with json, because respond_with is smart enough to do to_json on object you are doing respond_with.
Am I right in all those assumptions?
So the question is if we can use js.erb and json.erb(yes?) do you need to return the json at all ?
Maybe going a step back helps.
With AJAX form, the submit event goes through JavaScript first, and does not trigger the browser to invoke a POST '/data.json'.
If you look at the HTML that is generated by Rails with the remote: true option, you probably see a "onsubmit()" or similar callback. It is also the JavaScript, that processes a 'success' or 'error' event. I like the jQuery documentation for this: http://api.jquery.com/jQuery.ajax/
Your question is also somewhat opinionated, because JavaScript libraries such as Backbone.js, Ember.js or Angular, allow to fine-tune the process chain of a form submit even further.

How to use client side validation with remote => true rails 3.1

Normally we can use many ways to use ajax with validation like using validate plugin or using plain ajax(no rails ajax) like below
data using ajax requests
$.post("test.php", $("#testform").serialize());
In your situation it can be something like that.
$('#your_form').submit(function(event) {
event.preventDefault();
/* Email validation here.*/
$.ajax({
type: "POST",
url: $(this).attr('action'),
data: $(this).serialize(),
});
});
But, I wish to use client side validation with Real Rails ajax . Please help how to do this?
Maybe you'd like to use this gem
UPDATE 1:
Since you want to do this through ajax, validation can be handled through you controller.
# Let's assume your remote request hits index
def index
#object.create(params[:object])
respond_to do |format|
format.html # index.html.erb
format.js
end
end
Now, define an index.js.erb in the relevant views folder & render
<% if #object.new_record? %>
alert("Failed to upload record: <%= j #object.errors.full_messages.join(', ').html_safe %>");

Generate PDF file using AJAX call

I'm trying to generate a PDF file using AJAX call in Rails3. The following code generates a PDF file which I have created using PRAWN gem.
<%= link_to "Generate pdf", books_path(#book, :format => 'pdf') %>
I do not want user to view the PDF until they order it. So, the goal is to create a PDF file in the server.
Any ideas or thoughts much appreciated.
Use this, make sure your remote action does not return the PDF, but simple generates and stores it on the server.
link_to "Generate PDF", prepare_books_path(#book), :remote => true, :method => :put
This will work in Rails 3. If you're using jQuery, make sure to read this article on how to set things up correctly.
Your controller action may look like this:
def prepare
# Do your thing to generate the PDF
render :text => "PDF Generated", :status => 200
end
I used the PUT-method because you are altering the state of your data (e.g. you are generating something new, you don't want a bot or crawler to automatically call that).
Firstly, it beats me why you would do something on a request like generating a PDF, when the user is not expecting that action. Isn't better to only generate the pdf when the user requests for it?
Thanks Ariejan.
I modified your code as following and it did just what I wanted.
<%= link_to "Generate Story Book", pdfbook_stories_path(:format => 'pdf'), :remote => true %>
And for the controller,
def pdfbook
#stories = current_account.stories
respond_to do |format|
format.pdf {}
end
end

Ruby on rails: Remote Upload A File Using AJAX

I've successfully uploaded a file using PUT and html, but is there a way to upload a file in a ajax remote_form_for ?
I've tried this to no success:
<% remote_form_for #song,:html => { :multipart => true }, :url => { :action => 'upload' } do |f| %>
If you're using Rails 3, try the Remotipart gem. It makes AJAX style file uploads relatively painless.
http://rubygems.org/gems/remotipart
http://github.com/leppert/remotipart
The standard remote_form_for doesn’t understand multipart form submission so you can't actually do this without some leg-work as indicated by yoda above.
The other way to achieve this is by using an iframe.

Resources