你如何使用Ajax请求处理Rail的flash?

Jer*_*ung 75 ajax ruby-on-rails

我对我提出的解决方案非常满意.基本上,我有一个帮助方法重新加载内联闪存,然后我有一个after_filter,如果请求是xhr,清除闪存.有人有比这更简单的解决方案吗?

更新:上面的解决方案已在Rails 1.x中写回,不再受支持.

小智 63

您还可以使用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
Run Code Online (Sandbox Code Playgroud)

在application.js中添加一个全局的ajax处理程序.对于jquery做这样的事情:

$(document).ajaxError(function(event, request) {
  var msg = request.getResponseHeader('X-Message');
  if (msg) alert(msg);
});
Run Code Online (Sandbox Code Playgroud)

用您自己的javascript flash函数替换alert()或尝试jGrowl.

  • 此外,可以存储消息类型:`response.headers ["X-消息类型"] = flash_type`(而FLASH_TYPE返回最重要的类型(误差>成功>通知)此外,还可以使用`ajaxComplete`.然后以包括成功的情况下:'$(文件).ajaxComplete(功能(例如,请求,选择采用){fireFlash(request.getResponseHeader( 'X-消息'),request.getResponseHeader( 'X-消息类型')); });` (6认同)

Vic*_*r S 29

这是我的基于@emzero的版本,修改了jQuery,在Rails 3.2上进行了测试

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
Run Code Online (Sandbox Code Playgroud)

的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
});
Run Code Online (Sandbox Code Playgroud)

layout:application.html.haml

        #flash-message
            - flash.each do |name, msg|
                = content_tag :div, msg, :id => "flash_#{name}"
Run Code Online (Sandbox Code Playgroud)

  • 如果重新编写代码不返回字符串"错误,警告,通知"以及与twitter-bootstrap玩得很好https://gist.github.com/hbrandl/5253211 (3认同)
  • 伟大的编译,虽然不应该"$("#flash-message").ajaxComplete(函数(事件,请求)"是"$(文档)"? (2认同)

Sil*_*aru 15

这在js响应中是必需的

如果您使用的是RSJ:

page.replace_html :notice, flash[:notice]
flash.discard
Run Code Online (Sandbox Code Playgroud)

如果你使用jQuery:

$("#flash_notice").html(<%=escape_javascript(flash.delete(:notice)) %>');
Run Code Online (Sandbox Code Playgroud)

  • 看起来在Rails 3.1+中你需要使用`flash.discard(:notice)`而不是`flash.delete(:notice)` (3认同)

dbK*_*per 15

我是这样做的..

控制器:

respond_to do |format|
    flash.now[:notice] = @msg / 'blah blah...'
    format.html 
    format.js
  end
Run Code Online (Sandbox Code Playgroud)

视图:

<div id='notice'>
    <%= render :partial => 'layouts/flash' , :locals => { :flash => flash } %>
</div>        
Run Code Online (Sandbox Code Playgroud)

布局/ _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 %>
Run Code Online (Sandbox Code Playgroud)

post.js.erb

$("#notice").html("<%= escape_javascript(render :partial => 'layouts/flash' , :locals => { :flash => flash }).html_safe %>");
Run Code Online (Sandbox Code Playgroud)


Vik*_*ary 10

建立在别人之上 -

(我们将完整的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
Run Code Online (Sandbox Code Playgroud)
//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
}
Run Code Online (Sandbox Code Playgroud)


nak*_*ima 6

看起来你需要的是flash.now[:notice],它只在当前动作中可用,而在下一个动作中不可用.您可以在这里查看文档:http://api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html#M000327

  • 应该被称为flash.eventually而不是flash.now;) (3认同)

Aru*_*nan 5

在控制器中分配消息,如下所示:

  flash.now[:notice] = 'Your message'
Run Code Online (Sandbox Code Playgroud)

app/views/layouts/application.js.erb - Ajax请求的布局.在这里你可以简单地使用

  <%= yield %>
  alert('<%= escape_javascript(flash.now[:notice]) %>'); 
Run Code Online (Sandbox Code Playgroud)

或使用gritter的一些丰富的动画:http://boedesign.com/demos/gritter/

  <%= yield %>
  <% if flash.now[:notice] %>
    $.gritter.add({
      title: '--',
      text: '<%= escape_javascript(flash.now[:notice]) %>'
    });
  <% end %>
Run Code Online (Sandbox Code Playgroud)


kru*_*.ar 0

我能想到的唯一改进是使 page.reload_flash 成为默认值(不必将其放在每个 rjs 文件中,如果您不想重新加载闪存,则使其显式,例如 page.keep_flash。

我不知道从哪里开始,但了解一些轨道我确信这并不难。