Rails respond_to 重定向无效
Rails respond_to redirect not working
我的 Rails 应用中的创建控制器中的 respond_to 块在成功保存时没有重定向...我确信这是一个简单的解决方案,但我对 Rails 这是我第一次遇到这个问题。
表单设置为:remote => true,控制器如下...
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
虽然我在讨论这个主题,但条件的 else 部分的代码也没有 运行,除了 format.js {}
,它 运行 我的 create.js.erb 文件中的代码(暂时是警报)。
我正在使用 Rails 4.2.5。有人可以帮助我理解为什么重定向和警报不起作用吗?谢谢!
编辑以显示解决方案
根据 Rich 的回答,这是我想出的解决方案:
控制器:
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。
表单成功后,页面重定向到根目录。失败时,错误消息会闪烁,但表单不会刷新 - 用户输入的任何答案都会保留。
如果您的表单中有 remote: true
,控制器检测到的格式将是 format.js,这不会出现在您成功的 @store.save
部分中。
2 个选项:
- 默认为普通表单提交(通过删除
remote: true
)
- 通过添加
format.js
加载另一个 js.erb 文件,就像在 else 子句中一样,然后通过一些 javascript. 在那里进行错误处理
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
并只使用您想要的 return(redirect_to
将不起作用)。
Ajax
有几个规定你需要理解:
- Ajax cannot "redirect" (on its own)
- Ajax will be treated as
JS
in your Rails controller
- You have to "hack" the flash to get it working through
JS
如果你没有使用过Ajax,简单的解释就是它是一个"pseudo-request";它无需重新加载浏览器即可发送 HTTP 请求。
Ajax 的模式很简单:Ajax request > server > Ajax response
您不能通过 Ajax "redirect",除非您使用 javascript 解析响应。正如 Ajax 首字母缩写词(异步 Javascript 和 XML)所暗示的那样,响应预计为 XML(IE 无功能) .
--
要回答您的问题,您需要对 "flash" 消息使用 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
gem:
#app/controllers/stores_controller.rb
class StoresController < ApplicationController
respond_to :js, only: :create
def create
@store = ...
respond_with @store if @store.save
end
end
我的 Rails 应用中的创建控制器中的 respond_to 块在成功保存时没有重定向...我确信这是一个简单的解决方案,但我对 Rails 这是我第一次遇到这个问题。
表单设置为:remote => true,控制器如下...
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
虽然我在讨论这个主题,但条件的 else 部分的代码也没有 运行,除了 format.js {}
,它 运行 我的 create.js.erb 文件中的代码(暂时是警报)。
我正在使用 Rails 4.2.5。有人可以帮助我理解为什么重定向和警报不起作用吗?谢谢!
编辑以显示解决方案 根据 Rich 的回答,这是我想出的解决方案:
控制器:
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。
表单成功后,页面重定向到根目录。失败时,错误消息会闪烁,但表单不会刷新 - 用户输入的任何答案都会保留。
如果您的表单中有 remote: true
,控制器检测到的格式将是 format.js,这不会出现在您成功的 @store.save
部分中。
2 个选项:
- 默认为普通表单提交(通过删除
remote: true
) - 通过添加
format.js
加载另一个 js.erb 文件,就像在 else 子句中一样,然后通过一些 javascript. 在那里进行错误处理
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
并只使用您想要的 return(redirect_to
将不起作用)。
Ajax
有几个规定你需要理解:
- Ajax cannot "redirect" (on its own)
- Ajax will be treated as
JS
in your Rails controller- You have to "hack" the flash to get it working through
JS
如果你没有使用过Ajax,简单的解释就是它是一个"pseudo-request";它无需重新加载浏览器即可发送 HTTP 请求。
Ajax 的模式很简单:Ajax request > server > Ajax response
您不能通过 Ajax "redirect",除非您使用 javascript 解析响应。正如 Ajax 首字母缩写词(异步 Javascript 和 XML)所暗示的那样,响应预计为 XML(IE 无功能) .
--
要回答您的问题,您需要对 "flash" 消息使用 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
gem:
#app/controllers/stores_controller.rb
class StoresController < ApplicationController
respond_to :js, only: :create
def create
@store = ...
respond_with @store if @store.save
end
end