解決策 私が思いついたことにとても満足しています。基本的に、インラインでフラッシュをリロードするヘルパーメソッドがあり、リクエストがxhrの場合にフラッシュをクリアするafter_filterがあります。誰もそれよりも簡単な解決策を持っていますか?
更新:上記のソリューションはRails 1.xで書き戻され、サポートされなくなりました。
また、after_filterブロックを使用して、応答ヘッダーにフラッシュメッセージを保存し、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);
});
Alert()を独自のJavaScriptフラッシュ関数に置き換えるか、jGrowlを試してください。
そして、これは、Rails 3.2でテストされた、jQueryで動作するように修正された@emzeroに基づく私のバージョンです。
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}"
これは、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
表示:
<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オブジェクトを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]) %>');
または、グリッターを使用したいくつかのリッチアニメーション: 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ネイティブプロトタイプヘルパーを使用している場合)追加:
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
}
});
ビクター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
});
nobtrusive Flash と呼ばれるgemがあり、フラッシュメッセージを自動的にCookieにエンコードします。クライアント側のjavascriptはフラッシュをチェックし、好きな方法で表示します。これは、通常のリクエストとajaxリクエストの両方でシームレスに機能します。
ここに私のバージョンがあります(複数のフラッシュ通知と特殊文字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 bootstrap version):
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を更新/表示することです。これらのフラッシュメッセージを必要な効果で表示することができます。これを使った
render:text => "エラーが発生しました"、:status => 444
javascriptで
new AjaxRequest(... 、 OnFailure:function(transport){ $( "#notice")。update(transport .responseText); //メッセージを表示 } );
HTH
何人かの人が提案するように、応答ヘッダーでフラッシュメッセージを送信するために、application_controllerにいくつかの動作を含むエンジンを構築します。
私が考えることができる唯一の改善点は、page.reload_flashをデフォルトにすることです(すべてのrjsファイルに配置する必要がなく、page.keep_flashのようにフラッシュをリロードしたくない場合に有効にします)。
どこから始めればいいのかわかりませんが、いくつかのRailsを知っていれば、それほど難しくはないでしょう。
AJAX呼び出しを使用する場合は、redirect_toをコントローラーで使用しないでください。むしろ、フラッシュメッセージを明示的に示す必要があります。
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);
})
_
messagesクラスはメッセージをレンダリングするためのアンカーポイントであることに注意してください。このクラスは、ビューまたはアプリケーションレイアウトに存在する必要があります。 ERBを使用する場合、行は$('.messages').html("<%= j(render 'layouts/messages') %>");
になります
HAML/ERBに埋め込まれた上記のJavaScriptは、AJAXを使用するときにフラッシュメッセージを表示するための鍵です。他のすべてのコンポーネントは、非AJAX呼び出しに対して同じままです。
_your_ajax_method_in_the_controller.js.coffee
_または通常の.jsを使用できますが、Rails変数はJS/Coffeeで使用できません。ここで変数を使用しなくても、JSをラップすることを好みます。一貫したコードベースを維持するためにHAMLで。
Twitter Bootstrapメッセージをスタイリングするために利用するため、$(".alert").alert('close')
は通知をフェードアウトします。そして、messages部分的:
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;
}
_