Ajax 요청으로 Rail의 플래시를 어떻게 처리합니까?
나는 내가 생각 해낸 해결책에 매우 만족 합니다 . 기본적으로 플래시를 인라인으로 다시로드하는 도우미 메서드가 있고 요청이 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 ()를 자신의 자바 스크립트 플래시 함수로 바꾸거나 jGrowl을 사용해보세요.
그리고 여기에 Rails 3.2에서 테스트 된 jQuery와 함께 작동하도록 수정 된 @emzero를 기반으로 한 버전이 있습니다.
application_controller.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
// 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
});
레이아웃 : application.html.haml
#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 %>");
다른 사람 위에 구축-
(우리는 완전한 플래시 객체를 JSON으로 전달하여 브라우저에서 완전한 플래시 객체를 재구성 할 수있게합니다. 이것은 Rails에서 여러 플래시 메시지가 생성되는 경우 모든 플래시 메시지가 표시되도록하는 데 사용할 수 있습니다.)
#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 %>
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
}
});
플래시 메시지를 쿠키로 자동 인코딩하는 Unobtrusive Flash 라는 gem이 있습니다 . 클라이언트 측의 자바 스크립트는 플래시를 확인하고 원하는 방식으로 표시합니다. 이것은 일반 및 ajax 요청 모두에서 원활하게 작동합니다.
flash[type].blank?댓글에서 소수의 사람들이 언급 한대로 작동하지 않는 일부 사례를 수정하기 위해 Victor S의 답변을 수정했습니다 .
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
});
다음은 내 버전입니다 (여러 플래시 알림 및 특수 문자 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
내 커피 스크립트 내부 (트위터 부트 스트랩 버전) :
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>")
Another way would be update/display the "notice" div with the message from the your Ajax requests "OnFailure" handler. It gives you the ability to show these flash messages with required effect. I used this
render :text => "Some error happened", :status => 444
in the Javascript
new AjaxRequest(...
,
OnFailure:function(transport) {
$("#notice").update(transport.responseText);
// show the message
}
);
HTH
I build an engine that includes some behavior to the application_controller to send the flash message in the response header as some of you guys propose.
https://github.com/bonzofenix/flajax
The only improvement I can think of is making the page.reload_flash default (not having to put it on every rjs file, and make it expicit if you don't want to reload the flash, something like page.keep_flash.
I wouldn't know where to start but knowing some rails I'm sure it's not that hard.
In case you want to use AJAX calls redirect_to should not be used in the controller. Rather, flash message should be explicitly denoted:
In your_controller:
respond_to :js
def your_ajax_method
flash[:notice] = 'Your message!'
end
In the view that is named by 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);
})
Please, notice, that the messages class is an anchor point for rendering messages. This class should be present in your view or application layout. If you use ERB the line becomes $('.messages').html("<%= j(render 'layouts/messages') %>");
The above JavaScript embedded into HAML/ERB is the key to displaying flash messages when using AJAX. All other components remain the same for non-AJAX calls.
You may use your_ajax_method_in_the_controller.js.coffee or plain .js but then the rails variables won't be available to JS/Coffee. Even though I don't use variables here I prefer to wrap JS in HAML to keep consistent codebase.
I leverage Twitter Bootstrap for styling messages, thus $(".alert").alert('close') fades away the notice. And here is the messages partial:
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}"
Just in case, CSS for the alerts is below
.alert-messages {
position: fixed;
top: 37px;
left: 30%;
right: 30%;
z-index: 7000;
}
참고URL : https://stackoverflow.com/questions/366311/how-do-you-handle-rails-flash-with-ajax-requests
'Program Club' 카테고리의 다른 글
| Git은 기능 분기의 단일 파일을 마스터와 동일하게 재설정합니다. (0) | 2020.10.18 |
|---|---|
| 자격 증명으로 Jenkins Pipeline Git SCM을 확인 하시겠습니까? (0) | 2020.10.18 |
| Mercurial이 커밋에 사용하는 사용자 이름을 어떻게 설정합니까? (0) | 2020.10.18 |
| RS232 직렬 포트 위조 (0) | 2020.10.18 |
| 잭슨 + 빌더 패턴? (0) | 2020.10.18 |