Как вы справляетесь со вспышкой Rail с запросами Ajax?

Я очень доволен решением, которое я придумал. В принципе, у меня есть вспомогательный метод, который перезагружает встроенную флеш-память, а затем у меня есть after_filter, который очищает флеш, если запрос xhr. У кого-нибудь есть более простое решение?

Обновление . Решение выше было записано в 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.

И вот моя версия, основанная на @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 

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('
'+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 });

layout: 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)) %>'); 

Я сделал это так.

controller :

 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

<%= msg %>

<% end %>

post.js.erb

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

Основываясь на других –

(Мы передаем полный flash-объект как JSON, что позволяет нам восстановить полный Flash-объект в браузере. Это можно использовать для обеспечения отображения всех флэш-сообщений в случае, если 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

Назначьте сообщение в controllerе следующим образом:

  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 } }); 

Существует жемчужина под названием Unobruusive Flash, которая автоматически кодирует флеш-сообщения в файл cookie. Javascript на конце клиента проверяет наличие вспышки и отображает ее любым способом. Это работает без проблем как с обычными, так и с ajax-запросами.

Я изменил ответ Виктора 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('
'+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 });

Вот моя версия (работа с краткими флэш-уведомлениями и специальными символами кодировки 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):

 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("
#{decodeURIComponent(escape(msg))}
")

Другой способ – обновить / отобразить div «notice» с сообщением из вашего запроса Ajax «OnFailure». Это дает вам возможность показывать эти флеш-сообщения с требуемым эффектом. Я использовал это

  render: text => «Произошла некоторая ошибка»,: status => 444

в Javascript

  новый AjaxRequest (...

   ,
    OnFailure: функция (транспорт) {
       . $ ( "# Извещение") обновление (transport.responseText);
      // показать сообщение  
    }

 );

НТН

Я создаю движок, который включает некоторое поведение в application_controller для отправки флэш-сообщения в заголовке ответа, как это предлагают некоторые из вас, ребята.

https://github.com/bonzofenix/flajax

Единственное усовершенствование, о котором я могу думать, это сделать default.reload_flash по умолчанию (не нужно помещать его в каждый файл rjs и делать это, если вы не хотите перезагружать флеш, что-то вроде page.keep_flash.

Я не знаю, с чего начать, но зная некоторые rails, я уверен, что это не так сложно.

Если вы хотите использовать вызовы AJAX, redirect_to не следует использовать в controllerе. Скорее, флэш-сообщение должно быть явно обозначено:

В вашем_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); }) 

Пожалуйста, обратите внимание, что class сообщения является точкой привязки для визуализации сообщений. Этот class должен присутствовать в вашем представлении или макете приложения. Если вы используете ERB, линия становится $('.messages').html("<%= j(render 'layouts/messages') %>");

Вышеупомянутый JavaScript, встроенный в HAML / ERB, является ключом к отображению флэш-сообщений при использовании AJAX. Все остальные компоненты остаются неизменными для вызовов без AJAX.

Вы можете использовать your_ajax_method_in_the_controller.js.coffee или plain .js, но тогда переменные рельсов не будут доступны JS / Coffee. Хотя я не использую переменные здесь, я предпочитаю переносить JS в HAML, чтобы поддерживать постоянную кодовую базу.

Я использую Twitter Bootstrap для стилизации сообщений, поэтому $(".alert").alert('close') исчезает извещение. И вот частичные сообщения :

макеты / _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; } 
  • Rails form_for: remote => true не вызывает метод js
  • Как пропустить обратные вызовы ActiveRecord?
  • Rails - link_to helper с атрибутом data- *
  • Rails 3 эквивалент для периодически_call_remote
  • Запрос ActiveRecord OR Hash
  • Rails 3.1 и Image Assets
  • Как изменить привязку привязки по умолчанию к серверу разработки Rails 4.2?
  • Запрос ActiveRecord OR
  • Управление порядком проверки рельсов
  • Кнопка «Отправить форму» работает только после перезагрузки
  • Почему `config.time_zone`, кажется, ничего не делает?
  • Interesting Posts

    Visual Studio 2010 – рекомендуемые расширения

    Что использовать? MVC, MVP или MVVM или …?

    Максимальная длина имени файла в NTFS (Windows XP и Windows Vista)?

    Печать даты и времени в Windows cmd

    Как обрабатывать очень большие числа в Java без использования java.math.BigInteger

    Добавление сторонних баннеров в WEB-INF / lib автоматически с помощью Eclipse / Tomcat

    Что такое регулярное выражение, которое будет соответствовать действительному доменному имени без субдомена?

    Ярлык для открытия определенной закладки / URL в Chrome

    Аутентификация Windows IIS Express

    Получение имени элемента в XPATH

    Как разбить String на несколько значений?

    Как предотвратить Vista от необходимости повышения на patch.exe?

    Как скрыть учетную запись администратора и показать только главного пользователя на экране входа в Windows 7?

    Передача параметров в таблицу стилей XSLT через .NET

    Быстрое переключение между поисковыми системами в окне поиска Firefox?

    Давайте будем гением компьютера.