2016-01-29 6 views
2

Блок response_to в контроллере create в моем приложении Rails не перенаправляет на успешное сохранение ... Я уверен, что это простое решение, но я неопытен с Rails, и это первый время, когда я сталкиваюсь с этой проблемой.Rails reply_to redirect не работает

Форма устанавливается таким образом, что: дистанционное => верно, и контроллер выглядит следующим образом ...

def create 
    @store = current_user.stores.new(store_params) 

    respond_to do |format| 
     if @store.save 
      format.html { redirect_to root_path } 
     else 
      format.html { flash[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" 
      render "new" } 
      format.js {} 
     end 
    end 
end 

И пока я на эту тему, код из еще часть условие тоже не выполняется, за исключением format.js {}, который запускает код в моем файле create.js.erb (пока что предупреждение).

Я работаю с Rails 4.2.5. Может ли кто-нибудь помочь мне понять, почему перенаправление и предупреждение не работают? Спасибо!

РЕДАКТИРОВАНИЕ ПОКАЗАТЬ РЕШЕНИЕ На основании ответа Рича, вот решение, которое я придумал:

Контроллер:

def create 
    @store = current_user.stores.new(store_params) 

    flash.now[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" unless @store.save 

    respond_to do |format| 
     format.js 
    end 

    if @store.save 
     flash[:notice] = "New store created" 
    end 
end 

create.js.erb

<% if flash.now[:alert] %> 
    $("#alert_holder").empty(); 
    $("#alert_holder").append("<%= j flash.now[:alert] %>"); 
<% else %> 
    window.location.href = "<%= root_url %>"; 
<% end %> 

Обратите внимание, что мне нужно добавить котировки вокруг URL-адреса перенаправления.

В случае успеха формы страница перенаправляется на корень. При ошибке сообщение об ошибке мигает, но форма не обновляется - все ответы, которые пользователь ввел, остаются.

ответ

3

remote: true является запросом ajax.

Ajax является JavaScript, и как таковой будет вызывать format.js метод:

def create 
    @store = current_user.stores.new store_params 

    respond_to do |format| 
     if @store.save 
      format.js 
      format.html { redirect_to root_path } 
     else 
      format.js 
      format.html { flash[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" 
      render "new" } 
     end 
    end 
end 

Метод format.js будет вызывать /app/views/[:controller]/[:action].js.erb файл, который будет срабатывать любого из JS вас есть внутри него.

Если вы не хотите иметь js формат обработки ответа, вам придется избавиться от respond_to и просто то, что вы хотели бы вернуть (redirect_to не будет работать).


Ajax

Есть несколько оговорок, которые необходимо оценить с этим:

  • Ajax не может "перенаправить" (сам по себе)
  • Ajax будет рассматриваться как JS в вашем контроллере Rails
  • Вы должны «взломать» вспышка, чтобы она работает через JS

Если у вас нет опыта работы с Ajax, простое объяснение состоит в том, что это «псевдо-запрос»; он отправляет HTTP-запрос без перезагрузки браузера.

Шаблон для Ajax прост: Ajax request > server > Ajax response

Вы не можете «перенаправить» с помощью Ajax, если не разобрать ответ с помощью JavaScript. Поскольку аббревиатура Ajax (Asynchronous Javascript и XML) предполагает, что откликом будет являться XML (IE не работает).

-

Чтобы ответить на ваш вопрос, вы должны будете использовать flash.now для сообщения «флэш», и обработать ответ с вашей .js.erb файла:

def create 
    @store = current_user.stores.new store_params 
    flash.now[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" unless @store.save 

    respond_to do |format| 
     format.js 
     format.html 
    end 
end 

Это позволит вам звоните ...

#app/views/stores/create.js.erb 
<% if flash.now[:alert] %> alert("<%=j flash.now[:alert] %>"); <% end %> 
window.location.href = <%= root_url %>; 

Ref


Ваш новый код может быть немного улучшилось:

def create 
    @store = current_user.stores.new store_params 

    if @store.save 
     flash[:notice] = "New store created" 
    else 
     flash.now[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" 
    end 

    respond_to do |format| 
     format.js 
    end 
end 

Если вы хотите DRY ваш код еще больше, вы хотите посмотреть на responders перл:

#app/controllers/stores_controller.rb 
class StoresController < ApplicationController 
    respond_to :js, only: :create 

    def create 
     @store = ... 
     respond_with @store if @store.save 
    end 
end 
+0

Wow! Спасибо, это замечательное объяснение! – skwidbreth

+1

Это действительно здорово, я бы не подумал об этом сам. Благодарим за предоставление руководства для новичков Rails. – skwidbreth

+0

Я отредактировал свой вопрос, чтобы отобразить ответ, который я придумал, основываясь на вашем руководстве. Я должен был подстроить несколько вещей, но он отлично работает. – skwidbreth

2

Если в вашей форме remote: true, формат, который будет обнаружен контроллером, будет format.js, которого нет в вашем успешном разделе @store.save.

2 варианта:

  • По умолчанию к нормальной форме представить (путем удаления remote: true)
  • Загрузите другой js.erb файл, добавив format.js так же, как в предложении еще тогда сделать обработку ошибок там через некоторое JavaScript ,