我对我提出的解决方案非常满意.基本上,我有一个帮助方法重新加载内联闪存,然后我有一个after_filter,如果请求是xhr,清除闪存.有人有比这更简单的解决方案吗?
更新:上面的解决方案已在Rails 1.x中写回,不再受支持.
您还可以使用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
在application.js中添加一个全局的ajax处理程序.对于jquery做这样的事情:
$(document).ajaxError(function(event, request) { var msg = request.getResponseHeader('X-Message'); if (msg) alert(msg); });
用您自己的javascript flash函数替换alert()或尝试jGrowl.
这是我的基于@emzero的版本,修改了jQuery,在Rails 3.2上进行了测试
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
// 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(''+msg+''); 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 });
#flash-message - flash.each do |name, msg| = content_tag :div, msg, :id => "flash_#{name}"
这在js响应中是必需的
如果您使用的是RSJ:
page.replace_html :notice, flash[:notice] flash.discard
如果你使用jQuery:
$("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
我是这样做的..
控制器:
respond_to do |format| flash.now[:notice] = @msg / 'blah blah...' format.html format.js end
视图:
<%= render :partial => 'layouts/flash' , :locals => { :flash => flash } %>
布局/ _flash.html.erb
<% flash.each do |name, msg| %>x<% end %><%= msg %>
post.js.erb
$("#notice").html("<%= escape_javascript(render :partial => 'layouts/flash' , :locals => { :flash => flash }).html_safe %>");
建立在别人之上 -
(我们将完整的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
}
看起来你需要的是flash.now[:notice]
,它只在当前动作中可用,而在下一个动作中不可用.您可以在这里查看文档:http://api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html#M000327
在控制器中分配消息,如下所示:
flash.now[:notice] = 'Your message'
app/views/layouts/application.js.erb - Ajax请求的布局.在这里你可以简单地使用
<%= yield %> alert('<%= escape_javascript(flash.now[:notice]) %>');
或使用gritter的一些丰富的动画:http://boedesign.com/demos/gritter/
<%= yield %> <% if flash.now[:notice] %> $.gritter.add({ title: '--', text: '<%= escape_javascript(flash.now[:notice]) %>' }); <% end %>