Ruby-on-rails 你如何用 Ajax 请求处理 Rail 的 flash?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/366311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you handle Rail's flash with Ajax requests?
提问by Jerry Cheung
I'm pretty happy with the solutionthat I came up with. Basically, I have a helper method that reloads the flash inline, and then I have an after_filter that clear out the flash if the request is xhr. Does anyone have a simpler solution than that?
我对我提出的解决方案感到非常满意。基本上,我有一个辅助方法可以重新加载内联 Flash,然后我有一个 after_filter 可以在请求是 xhr 时清除 Flash。有没有人有比这更简单的解决方案?
Update:The solution above was written back in Rails 1.x and is no longer supported.
更新:上面的解决方案是在 Rails 1.x 中写回的,不再受支持。
回答by gudleik
You can also store the flash messages in the response headers using a after_filter block and display them using javascript:
您还可以使用 after_filter 块将 flash 消息存储在响应标头中,并使用 javascript 显示它们:
class ApplicationController < ActionController::Base
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash[:error] unless flash[:error].blank?
# repeat for other flash types...
flash.discard # don't want the flash to appear when you reload page
end
And in application.js add a global ajax handler. For jquery do something like this:
并在 application.js 中添加一个全局 ajax 处理程序。对于 jquery 做这样的事情:
$(document).ajaxError(function(event, request) {
var msg = request.getResponseHeader('X-Message');
if (msg) alert(msg);
});
Replace alert() with your own javascript flash function or try jGrowl.
用您自己的 javascript flash 函数替换 alert() 或尝试 jGrowl。
回答by Victor S
And here is my version based on @emzero, with modifications to work with jQuery, tested on Rails 3.2
这是我基于@emzero 的版本,经过修改以使用 jQuery,在 Rails 3.2 上测试
application_controller.rb
应用控制器.rb
class ApplicationController < ActionController::Base
protect_from_forgery
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash_message
response.headers["X-Message-Type"] = flash_type.to_s
flash.discard # don't want the flash to appear when you reload page
end
private
def flash_message
[:error, :warning, :notice].each do |type|
return flash[type] unless flash[type].blank?
end
end
def flash_type
[:error, :warning, :notice].each do |type|
return type unless flash[type].blank?
end
end
end
application.js
应用程序.js
// FLASH NOTICE ANIMATION
var fade_flash = function() {
$("#flash_notice").delay(5000).fadeOut("slow");
$("#flash_alert").delay(5000).fadeOut("slow");
$("#flash_error").delay(5000).fadeOut("slow");
};
fade_flash();
var show_ajax_message = function(msg, type) {
$("#flash-message").html('<div id="flash_'+type+'">'+msg+'</div>');
fade_flash();
};
$(document).ajaxComplete(function(event, request) {
var msg = request.getResponseHeader('X-Message');
var type = request.getResponseHeader('X-Message-Type');
show_ajax_message(msg, type); //use whatever popup, notification or whatever plugin you want
});
layout: application.html.haml
布局:application.html.haml
#flash-message
- flash.each do |name, msg|
= content_tag :div, msg, :id => "flash_#{name}"
回答by dbKooper
I did it this way..
我是这样做的。。
controller:
控制器:
respond_to do |format| flash.now[:notice] = @msg / 'blah blah...' format.html format.js end
respond_to do |format| flash.now[:notice] = @msg / 'blah blah...' format.html format.js end
view:
看法:
<div id='notice'>
<%= render :partial => 'layouts/flash' , :locals => { :flash => flash } %>
</div>
layouts/_flash.html.erb
布局/_flash.html.erb
<% flash.each do |name, msg| %>
<div class="alert-message info">
<a class="close dismiss" href="#">x</a>
<p><%= msg %></p>
</div>
<% end %>
post.js.erb
post.js.erb
$("#notice").html("<%= escape_javascript(render :partial => 'layouts/flash' , :locals => { :flash => flash }).html_safe %>");
回答by Silviu Postavaru
This is needed in the js response
这在 js 响应中是必需的
If you are using RSJ:
如果您使用的是 RSJ:
page.replace_html :notice, flash[:notice]
flash.discard
If you are using jQuery:
如果您使用 jQuery:
$("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
回答by Vikrant Chaudhary
Building on top of others -
建立在其他人之上 -
(We pass the complete flash object as JSON, enabling us to reconstruct the complete flash object in the browser. This can be used to ensure that all flash messages are displayed in case multiple flash messages are generated by Rails.)
(我们将完整的 flash 对象作为 JSON 传递,使我们能够在浏览器中重建完整的 flash 对象。这可用于确保在 Rails 生成多个 flash 消息的情况下显示所有 flash 消息。)
#application_controller.rb
class ApplicationController < ActionController::Base
after_filter :flash_to_headers
def flash_to_headers
if request.xhr?
#avoiding XSS injections via flash
flash_json = Hash[flash.map{|k,v| [k,ERB::Util.h(v)] }].to_json
response.headers['X-Flash-Messages'] = flash_json
flash.discard
end
end
end
//application.js
$(document).ajaxComplete(function(event, request){
var flash = $.parseJSON(request.getResponseHeader('X-Flash-Messages'));
if(!flash) return;
if(flash.notice) { /* code to display the 'notice' flash */ $('.flash.notice').html(flash.notice); }
if(flash.error) { /* code to display the 'error' flash */ alert(flash.error); }
//so forth
}
回答by nakajima
Looks like what you need is flash.now[:notice], which is only available in the current action and not in the next. You can take a look at the documentation here: http://api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html#M000327
看起来您需要的是flash.now[:notice],它仅在当前操作中可用,而在下一个操作中不可用。您可以在此处查看文档:http: //api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html#M000327
回答by Arun Kumar Arjunan
Assign the message in the controller like this:
像这样在控制器中分配消息:
flash.now[:notice] = 'Your message'
app/views/layouts/application.js.erb - Layout for Ajax Requests. Here you can simply use
app/views/layouts/application.js.erb - Ajax 请求的布局。在这里你可以简单地使用
<%= yield %>
alert('<%= escape_javascript(flash.now[:notice]) %>');
or with some rich animations using gritter: http://boedesign.com/demos/gritter/
或使用 gritter 制作一些丰富的动画:http://boedesign.com/demos/gritter/
<%= yield %>
<% if flash.now[:notice] %>
$.gritter.add({
title: '--',
text: '<%= escape_javascript(flash.now[:notice]) %>'
});
<% end %>
回答by emzero
Based on gudleik answer:
基于 gudleik 的回答:
class ApplicationController < ActionController::Base
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash_message
response.headers["X-Message-Type"] = flash_type
flash.discard # don't want the flash to appear when you reload page
end
private
def flash_message
[:error, :warning, :notice].each do |type|
return flash[type] unless flash[type].blank?
end
end
def flash_type
[:error, :warning, :notice].each do |type|
return type unless flash[type].blank?
end
end
Then on your application.js (if you're using Rails native Prototype helpers) add:
然后在您的 application.js(如果您使用 Rails 原生 Prototype 助手)上添加:
Ajax.Responders.register({
onComplete: function(event, request) {
var msg = request.getResponseHeader('X-Message');
var type = request.getResponseHeader('X-Message-Type');
showAjaxMessage(msg, type); //use whatever popup, notification or whatever plugin you want
}
});
回答by Ricky Gu
I modified Victor S' answer to fix some cases where flash[type].blank?didn't work as noted by few people in the comments.
我修改了 Victor S 的答案,以修复一些flash[type].blank?在评论中很少有人指出不起作用的情况。
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash_message
response.headers["X-Message-Type"] = flash_type.to_s
flash.discard # don't want the flash to appear when you reload page
end
private
def flash_message
[:error, :warning, :notice, nil].each do |type|
return "" if type.nil?
return flash[type] unless flash[type].blank?
end
end
def flash_type
[:error, :warning, :notice, nil].each do |type|
return "" if type.nil?
return type unless flash[type].blank?
end
end
Then rest is the same
然后休息是一样的
// FLASH NOTICE ANIMATION
var fade_flash = function() {
$(".flash_notice").delay(5000).fadeOut("slow");
$(".flash_alert").delay(5000).fadeOut("slow");
$(".flash_error").delay(5000).fadeOut("slow");
};
var show_ajax_message = function(msg, type) {
$(".flash_message").html('<div class="flash_'+type+'">'+msg+'</div>');
fade_flash();
};
$( document ).ajaxComplete(function(event, request) {
var msg = request.getResponseHeader('X-Message');
var type = request.getResponseHeader('X-Message-Type');
show_ajax_message(msg, type); //use whatever popup, notification or whatever plugin you want
});
回答by Luc Boissaye
Here is my version (working with multiples flash notices and special characters UTF-8 encoding):
这是我的版本(使用多个 Flash 通知和特殊字符 UTF-8 编码):
Inside ApplicationController:
内部应用程序控制器:
after_filter :flash_to_headers
def flash_to_headers
return unless request.xhr?
[:error, :warning, :notice].each do |type|
if flash[type]
response.headers["X-Ajax-#{type.to_s.humanize}"] = flash[type]
end
end
flash.discard
end
Inside my coffee-script (twitter bootstrap version):
在我的咖啡脚本中(twitter bootstrap 版本):
css_class = {
Notice: 'success',
Warning: 'warning',
Error: 'error'
}
$(document).ajaxComplete (event, request) ->
for type in ["Notice", "Warning", "Error"]
msg = request.getResponseHeader("X-Ajax-#{type}")
if msg?
$('#notices').append("<div class=\"alert #{css_class[type]}\">#{decodeURIComponent(escape(msg))}</div>")

