Как вы перенаправляете на страницу, когда ответ продолжает возвращаться в формате JSON?

Я использую dropzone.js для загрузки изображений.

В моем js-файле coffeescript у меня есть настройка для 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

Помимо вариантов, нажатие кнопки отправки в моей форме, если присутствует изображение, будет обрабатывать изображение, а если изображения нет, форма все равно будет отправлена.

Далее мой контроллер (соответствующий код):

  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

Чем моя форма:

= 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'

Итак, теперь в этой настройке все работает. Прежде чем я получил ошибку Missing Template, потому что мне нужно было создать шаблон show.json.erb, и после того, как я это сделал, в журнале появляется следующее:

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)

Итак, теперь мне интересно, при использовании JSON или просто в этом сценарии все вместе, как мне перенаправить на страницу отображения элемента, если она продолжает заставлять меня использовать JSON?

ОБНОВИТЬ

При изменении моего ответа при сохранении элемента:

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

Он делает это:

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)

Итак, я думаю, как я должен делать GET запросы в виде HTML, чтобы он работал правильно?

ОБНОВЛЕНИЕ 2

Я сделал следующее ниже и также должен был создать файл create.json.erb.

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.....

Он по-прежнему не перенаправляет меня, давая мне те же результаты, что и раньше.

ОБНОВЛЕНИЕ 3

Таким образом, format.json { redirect_to item_path(@item) and return} не перенаправляет на страницу показа, а обрабатывает в JSON. И выполнение format.json { redirect_to item_path(@item, format: :html) and return} оставляет мне Started GET "/items/19.html, что неправильно, поскольку вы не можете получить страницу с .html в конце.

ОБНОВЛЕНИЕ 3

Все еще не повезло с любой вариацией:

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

Я думаю, что мне нужно перенаправить с помощью window.location, который является частью JavaScript, где-то в моем коде, но мне нужно провести больше исследований. Меня не волнует, смогу ли я заставить это работать в формате js или html, пока это работает.

ОБНОВЛЕНИЕ 4

Итак, я смог получить такое же поведение в новом тестовом приложении на моем GitHub здесь: https://github.com/justintech/dropzonetest. Это выдает Invalid JSON response from server. Итак, я предполагаю, что мое реальное приложение делает то же самое, но оно просто дает сбой и проходит как полный ответ. странный. Не стесняйтесь проверить это.


person John Huntington    schedule 17.10.2015    source источник
comment
что бы вы хотели ответить, если ваше действие create_action (в формате JSON) будет успешным?   -  person illusionist    schedule 25.10.2015
comment
@illusionist HTML, если возможно.   -  person John Huntington    schedule 26.10.2015
comment
если вы никогда не будете отвечать в формате JSON, вы можете удалить все операторы format.json {} и убедиться, что все запросы, которые может сделать клиент, находятся в HTML запросах.   -  person illusionist    schedule 26.10.2015
comment
вам в итоге понадобился файл js.erb? это не показано в коде, но вы упомянули об этом. я смог заставить мой аналогичный проект работать без него.   -  person Timmy Von Heiss    schedule 15.08.2016
comment
Вы проверили, что код контроллера else работал при сбое?   -  person Timmy Von Heiss    schedule 15.08.2016


Ответы (3)


Забудьте о разделе формата, если вы хотите, чтобы оба формата реагировали одинаково. Все, что вам нужно, это перенаправление. Попробуйте просто redirect_to(@item).

Изменить:

Я посмотрел ваш код. Я обнаружил, что работает следующее:

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

в пунктах.кофе:

$(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
person Bassel Samman    schedule 25.10.2015
comment
Это не работает. Вот в чем была первоначальная проблема, поэтому я должен отформатировать ее или что-то в этом роде. Как-то странно работает Dropzone.js. - person John Huntington; 26.10.2015
comment
Хорошо, вы уверены, что сохранение прошло успешно? Возможно, он терпит неудачу и пытается вместо этого отобразить. Вы можете изменить направление рендеринга, передав ему параметр местоположения. - person Bassel Samman; 26.10.2015
comment
если вы посмотрите на UPDATE 2 выше, он завершит сохранение и сможет получить доступ к странице отображения элементов. Это просто перенаправление, которое не происходит. Область изображения dropzone.js будет обработана, и после ее завершения эта страница останется прежней. - person John Huntington; 26.10.2015
comment
На самом деле то, что вы делали изначально, было правильно, так что это странно. Вы можете попробовать настроить его на всякий случай: format.json { render :show, status: :created, location: item_url(@item)} - person Bassel Samman; 26.10.2015
comment
Я попытался изменить статус на success и redirect, а также формат на html, но все равно не повезло. - person John Huntington; 26.10.2015
comment
@JohnHuntington, не могли бы вы помочь мне написать dropzone.on 'failure' в этом вопросе -- stackoverflow.com/questions/38960487/ - person Timmy Von Heiss; 15.08.2016

Если вы хотите redirect_to items show страницу, которую вы делаете для формата html, почему бы просто не сделать то же самое и для формата json?:

  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
person K M Rakibul Islam    schedule 17.10.2015
comment
Спасибо, пока это похоже на то, что я на правильном пути. Проверьте мое редактирование, чтобы увидеть, что происходит, когда я делаю, как вы говорите. - person John Huntington; 17.10.2015
comment
Как насчет redirect_to item_path(@item, format: :html)? - person K M Rakibul Islam; 17.10.2015
comment
Это странно. Он возвращает Processing by ItemsController#show as HTML , как и должно быть, но остается на той же странице. - person John Huntington; 17.10.2015
comment
не могли бы вы попробовать: redirect_to item_path(@item, format: :html) and return? - person K M Rakibul Islam; 17.10.2015
comment
Это заставляет меня создать create.json.erb, который отображает Rendered items/create.json.erb. Если я не помещаю это в нужное место. Проверьте мое редактирование, если вам нужно. - person John Huntington; 17.10.2015
comment
В этот момент. не совсем уверен, что это действительно возможно. Не могли бы вы опубликовать свой routes.rb файл? Я посмотрю и вернусь к вам. - person K M Rakibul Islam; 17.10.2015
comment
Это мои маршруты по этой основной ссылке: gist.github.com/justintech/db7bfa5b494d77b7ad2d - person John Huntington; 17.10.2015
comment
он должен быть обработан действием show, НО не create. - person K M Rakibul Islam; 17.10.2015
comment
попробуйте именно это: format.json { redirect_to item_path(@item, format: :html) and return} ваше возвращение за пределы блока. - person K M Rakibul Islam; 17.10.2015
comment
Я думаю, что вижу проблему. Предполагается ли это сделать? Started GET "/items/19.html? Со словом .html в конце ссылки. Это выглядит странно. - person John Huntington; 17.10.2015
comment
может быть потому, что мы указали: format: :html, если вы удалите это, то оно должно исчезнуть. - person K M Rakibul Islam; 17.10.2015
comment
Не могли бы вы воспроизвести проблему в отдельном проекте и поделиться ссылкой на github, чтобы мы могли посмотреть локально? - person K M Rakibul Islam; 27.10.2015
comment
Итак, я смог получить такое же поведение в новом тестовом приложении на моем GitHub здесь: github.com/ justintech/dropzonetest. Это выдает Invalid JSON response from server. Итак, я предполагаю, что мое настоящее приложение делает то же самое, но оно просто дает сбой и проходит как завершенное. странный. - person John Huntington; 27.10.2015
comment
Я пытался заставить его работать так, как вы хотите, но кажется, что ничего не работает так, как вы хотите. Попробуйте думать по-другому, попробуйте снова подумать об исходной проблеме. Какова ваша конечная цель? Чего вы действительно хотите достичь? Я уверен, что есть лучший способ сделать это! Просто нужно подойти к проблеме под другим углом. - person K M Rakibul Islam; 27.10.2015
comment
Да, я думал о добавлении изображения на другую страницу. Ну хорошая попытка. Я ценю это. - person John Huntington; 27.10.2015

к вашему сведению

Ваше предложение:
format.json { redirect_to item_path(@item, format: :html) and return} оставляет мне Started GET "/items/19.html, что неверно, поскольку вы не можете получить страницу с .html в конце.

это не обрабатывается, как вы думаете; Rails не ищет какую-либо страницу типа 1.html, он передает число 1 как params[:id] = 1 и html в качестве формата запроса.

Так как в запросе есть .html

format.html {} активирован, иначе format.json {} был бы активирован, если бы запрос был /1.json

person illusionist    schedule 25.10.2015
comment
Но даже если format.html активирован. Он по-прежнему будет использовать JSON для отправки моей формы. Хотя это нормально. Все, что я хочу сделать, это после того, как он обработает мое изображение, перейти на следующую страницу, возможно ли это с помощью HTML или JS. - person John Huntington; 26.10.2015
comment
как подается форма; через AJAX или обычный Form submit? ; кроме того, стандарт говорит, что если клиент запрашивает JSON, вы должны ответить JSON данными, несмотря ни на что. - person illusionist; 26.10.2015
comment
Он отправляется JSON, когда изображения присутствуют, но если изображения нет, он будет выполнять обычный HTML. - person John Huntington; 26.10.2015