我对提出的解决方案感到非常满意。基本上,我有一个帮助程序方法可以重新内联刷新Flash,然后有一个after_filter可以清除Flash(如果请求是xhr)。有没有人比这更简单的解决方案?
更新:上面的解决方案是用Rails 1.x写回的,不再受支持。
Answers:
您还可以使用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。
response.headers['X-Message-Type'] = flash_type
而flash_type返回最重要的类型(错误>成功>通知)。此外,您还可以使用ajaxComplete
它包括成功案例:$(document).ajaxComplete(function(e, request, opts) { fireFlash(request.getResponseHeader('X-Message'), request.getResponseHeader('X-Message-Type')); });
这是我基于@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('<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
});
#flash-message
- flash.each do |name, msg|
= content_tag :div, msg, :id => "flash_#{name}"
3.1.0
。感谢Victor,为我开箱即用。
[:error, :warning, :notice].each {}
如果不满足返回条件,则返回数组,因此此代码需要进行一些调整。
js响应中需要
如果您使用的是RSJ:
page.replace_html :notice, flash[:notice]
flash.discard
如果您使用的是jQuery:
$("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
flash.discard(:notice)
而不是flash.delete(:notice)
我是这样做的。
控制器:
respond_to do |format|
flash.now[:notice] = @msg / 'blah blah...'
format.html
format.js
end
视图:
<div id='notice'>
<%= render :partial => 'layouts/flash' , :locals => { :flash => flash } %>
</div>
layouts / _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
$("#notice").html("<%= escape_javascript(render :partial => 'layouts/flash' , :locals => { :flash => flash }).html_safe %>");
flash.now[:notice]= @msg / 'blah blah..'
我也很好奇,您会将post.js.erb放在路径app / assets / javascripts中,对吗?
建立在他人之上-
(我们将完整的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
}
$.each( $.parseJSON(request.getResponseHeader('X-Flash-Messages')), function(key,value){ flash_message(key,value) });
如果您具有js函数来显示具有Flash和Message的参数类型的Flash消息,则我将application.js中的函数修改为喜欢
看起来您需要的是flash.now[:notice]
,仅在当前操作中可用,而在下一个操作中不可用。您可以在此处查看文档:http : //api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html#M000327
flash.now
是解决另一个问题的方法。flash.now
Ajax回调不会神奇地将的内容插入当前页面。
像这样在控制器中分配消息:
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 %>
基于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
然后在您的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
}
});
return unless request.xhr
吗?我在当前请求结束的意思是如果我们已经添加任何闪光的通知,我们将它们添加到那么响应头在我们阅读这些JS -冷静,但我不知道是什么原因,我们有上述行
有一个名为Unobtrusive Flash的gem ,它可以将Flash消息自动编码为cookie。客户端的javascript检查Flash并以您想要的任何方式显示它。这可以在普通请求和ajax请求中无缝运行。
我修改了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
那休息就一样了
// 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
});
这是我的版本(使用多个Flash通知和特殊字符UTF-8编码):
在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
在我的咖啡脚本(Twitter引导程序版本)中:
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>")
另一种方法是使用来自Ajax请求“ OnFailure”处理程序的消息更新/显示“ notice” div。它使您能够以所需的效果显示这些Flash消息。我用这个
渲染:text =>“发生一些错误”,:status => 444
在Javascript中
新的AjaxRequest(... , OnFailure:function(transport){ $(“#notice”)。update(transport.responseText); //显示讯息 } );
高温超导
我构建了一个引擎,其中包含一些对application_controller的行为,以按照某些人的建议在响应标头中发送Flash消息。
如果要使用AJAX调用,则不应在控制器中使用redirect_to。相反,应明确表示Flash消息:
在your_controller中:
respond_to :js
def your_ajax_method
flash[:notice] = 'Your message!'
end
在由your_ajax_method_in_the_controller命名的视图中
your_ajax_method_in_the_controller.js.haml
:plain
$("form[data-remote]")
.on("ajax:success", function(e, data, status, xhr) {
$('.messages').html("#{escape_javascript(render 'layouts/messages')}");
setTimeout(function(){ $(".alert").alert('close') }, 5000);
})
请注意,消息类是呈现消息的锚点。此类应出现在您的视图或应用程序布局中。如果您使用ERB,则该行将变为$('.messages').html("<%= j(render 'layouts/messages') %>");
嵌入到HAML / ERB中的上述JavaScript是使用AJAX时显示Flash消息的关键。对于非AJAX调用,所有其他组件保持不变。
您可以使用your_ajax_method_in_the_controller.js.coffee
.js或Plain .js,但是JS / Coffee将无法使用rails变量。即使我在这里不使用变量,我还是更喜欢将JS包装在HAML中以保持一致的代码库。
我利用Twitter Bootstrap对消息进行样式设置,从而$(".alert").alert('close')
淡化了通知。这是部分消息:
layouts / _messages.html.haml
- flash.each do |name, msg|
- if msg.is_a?(String)
.alert-messages
%div{class: "alert alert-#{name == :notice ? "success" : "error"} fade in"}
%a.close{"data-dismiss" => "alert"}
%i.icon-remove-circle
= content_tag :div, msg, id: "flash_#{name}"
以防万一,警报的CSS如下
.alert-messages {
position: fixed;
top: 37px;
left: 30%;
right: 30%;
z-index: 7000;
}
after_filter { flash.discard if request.xhr? }