Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you redirect to a page when the response keeps returning in JSON?

I'm using dropzone.js for image uploads.

In my coffeescript js file I have the setup for dropzone:

Dropzone.autoDiscover = false

dropzone = new Dropzone('#item-form',
  maxFiles: 1
  maxFilesize: 1
  paramName: 'item[image]'
  headers: "X-CSRF-Token" : $('meta[name="csrf-token"]').attr('content')
  addRemoveLinks: true
  clickable: '#image-preview'
  previewsContainer: '#image-preview'
  thumbnailWidth: 200
  thumbnailHeight: 200
  parallelUploads: 100;
  autoProcessQueue: false
  uploadMultiple: false)

$('#item-submit').click (e) ->
  e.preventDefault()
  e.stopPropagation()
  if dropzone.getQueuedFiles().length > 0
    dropzone.processQueue()
  else
    $('#item-form').submit()
  return
return

Besides from the options, the clicking of the submit button on my form, if there is an image present, will process the image and if there's no image will submit the form anyways.

Next is my controller (relevant code):

  def create
    @item = current_user.items.build(item_params)

    respond_to do |format|
      if @item.save
        format.html { redirect_to @item, notice: 'Item was successfully created.' }
        format.json { render :show, status: :created, location: @item }
      else
        format.html { render :new }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

Than my form:

= form_for @item, html: {id: 'item-form', class: 'form', multipart: true} do |f|
 = f.text_field :name, class: 'form-control'

    %main#image-preview
     Add a Photo
     .fallback
      = f.file_field :image, multiple: false

= f.submit 'Done', id: 'item-submit'

So now this setup has everything working. Before I got a Missing Template error because I needed to create a show.json.erb template and after I did that it gives me this in the log:

Started POST "/items" for 127.0.0.1 at 2015-10-16 21:36:18 -0700
Processing by ItemsController#create as JSON
...................
   (10.7ms)  COMMIT
  Item Store (142.4ms)  {"id":12}
  Rendered items/show.json.erb (0.4ms)
Completed 201 Created in 2759ms (Views: 6.1ms | Searchkick: 142.4ms | ActiveRecord: 11.9ms)

So now I'm wondering when using JSON or just in this scenario all together, how do I redirect to the item show page if it keeps forcing me to use JSON?

UPDATE

When changing my response when item is saved:

if @item.save
  format.html { redirect_to @item }
  format.json { redirect_to @item }
else

It does this:

Started GET "/items/13" for 127.0.0.1 at 2015-10-16 22:54:29 -0700
Processing by ItemsController#show as JSON
  Parameters: {"id"=>"13"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 2]]
  Item Load (0.4ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = $1 LIMIT 1  [["id", 13]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 2]]
  Rendered items/show.json.erb (0.7ms)
Completed 200 OK in 137ms (Views: 7.5ms | ActiveRecord: 25.2ms)

So I believe some how I have to do a GET requests as HTML in order for it to do right?

UPDATE 2

I did the following below and had to create a create.json.erb file as well.

if @item.save
  format.html { redirect_to @item }
  format.json { redirect_to item_path(@item, format: :html) } and return
else

Started POST "/items" for 127.0.0.1 at 2015-10-16 23:36:13 -0700
Processing by ItemsController#create as JSON............

   (12.9ms)  COMMIT
  Item Store (426.1ms)  {"id":18}
  Rendered items/create.json.erb (19.6ms)
Completed 200 OK in 3892ms.....

It still doesn't redirect me giving me the same results as before.

UPDATE 3

So doing format.json { redirect_to item_path(@item) and return} does not redirect to the show page but processes in JSON. And doing format.json { redirect_to item_path(@item, format: :html) and return} leaves me with Started GET "/items/19.html which is wrong since you can't get a page with .html at the end.

UPDATE 3

Still no luck with any variation of:

format.json {render :show, status: :created, location: item_url(@item, format: :html )}

I'm thinking I have to redirect with window.location which is apart of JavaScript, somewhere in my code but need to do more research. I don't care if I can get this working in js or html format as long as it works.

UPDATE 4

Okay, so I was able to get the same behavior in a brand new test app at my GitHub here: https://github.com/justintech/dropzonetest. This one throws the Invalid JSON response from server. So I'm guessing that my real app does the same thing but it just glitches and passes as a complete response. weird. Feel free to check it out.

like image 582
John Huntington Avatar asked Oct 17 '15 04:10

John Huntington


2 Answers

Forget the format section if you want both formats to respond the same. All you need is the redirect. Try just redirect_to(@item).

Edit:

I looked at your code. I found that the following works:

items_controller.rb:

def create
  @item = Item.new(item_params)

  respond_to do |format|
    if @item.save
      format.html { redirect_to @item, notice: 'Item was successfully created.' }
      format.json { render json: @item }
    else
      format.html { render :new }
      format.json { render json: @item.errors, status: :unprocessable_entity }
    end
  end
end

in items.coffee:

$(document).ready ->
  # disable auto discover
  Dropzone.autoDiscover = false

  dropzone = new Dropzone('#item-form',
    maxFiles: 1
    maxFilesize: 1
    paramName: 'item[image]'
    headers: "X-CSRF-Token" : $('meta[name="csrf-token"]').attr('content')
    addRemoveLinks: true
    clickable: '#image-preview'
    previewsContainer: '#image-preview'
    thumbnailWidth: 200
    thumbnailHeight: 200
    parallelUploads: 100;
    autoProcessQueue: false
    uploadMultiple: false)

  $('#item-submit').click (e) ->
    e.preventDefault()
    e.stopPropagation()
    if dropzone.getQueuedFiles().length > 0
      dropzone.processQueue()
    else
      $('#item-form').submit()

  dropzone.on 'success', (file, responseText) ->
    window.location.href = '/items/' + responseText.id
like image 144
Bassel Samman Avatar answered Nov 16 '22 11:11

Bassel Samman


If you want to redirect_to the items show page which you do for your html format, why not just do the same for json format as well?:

  if @item.save
    format.html { redirect_to @item, notice: 'Item was successfully created.' }
    format.json { redirect_to @item, notice: 'Item was successfully created.' }
  # rest of your codes
  end
like image 6
K M Rakibul Islam Avatar answered Nov 16 '22 09:11

K M Rakibul Islam