СУШКА некоторого кода представления Rails/HAML/jQuery

Я визуализирую панель предупреждений как часть в верхней части экрана, которая отображается пользователю для сообщений об успехе / неудаче / уведомлении.

Наконец-то у меня это работает для большинства сценариев, но сам код повторяется для нескольких частей, и я не уверен, как можно разделить его более эффективно, поскольку я относительно новичок во всем этом. Моя цель - попытаться не повторяться, если это возможно, или, по крайней мере, минимизировать количество повторений.

Например, есть ли способ поместить часть JavaScript в повторно используемую частичную или вспомогательную функцию? Существуют ли другие очевидные способы сделать этот код менее повторяющимся?

С Rails/Ruby я еще не достаточно разбираюсь, чтобы понять, как улучшить код, поэтому любые советы, которые вы можете дать, будут высоко оценены!

/ top alert area
#topAlertBar.shadow_medium.soft-hidden

- if flash.empty? && !current_user.confirmed?
  - # User has yet to confirm their account
  - # and there AREN'T any flash messages to show

  #alertBarOffset.colordark.soft-hidden
    / placeholder for alert bar offset

  :javascript
    // Set the flash box content
    $('#topAlertBar').html('Please confirm your account by following the instructions sent to #{current_user.email}.  To resend your confirmation email, #{escape_javascript(link_to("click here", user_resend_confirmation_path(current_user), :class => "inlinelink", :method => :post, :remote => true))} #{escape_javascript(image_tag("ajaxOrange.gif", :class => "soft-hidden mls mbs"))}.');

    // Slides down the top alert bar after page load
    $('#topAlertBar, #alertBarOffset').delay(250).slideDown("fast");

    // Shows & hides AJAX loading GIF when necessary
    $('#topAlertBar a').click(function() {
      $(document).bind('ajaxSend', function(e, request, options) {
        $("#topAlertBar img").show();
      });
      $(document).bind('ajaxComplete', function(e, request, options) {
        $(document).unbind('ajaxSend', 'ajaxComplete');
        $("#topAlertBar img").hide();
      });
    });

- elsif !flash.empty? && !current_user.confirmed?
  - # User has yet to confirm their account
  - # and there ARE flash messages to show

  #alertBarOffset.colordark.soft-hidden
    / placeholder for alert bar offset

  - [:error, :success, :notice].each do |key| 
    - unless flash[key].blank?
      - @msg = flash[key]
      - @key = key

  :javascript
    // Set the flash box content
    var $that = $('#topAlertBar');
    $that.html('#{@msg}').addClass('#{@key}').delay(250).slideDown("fast", function() {
      $(this).delay(2000).slideUp("fast", function () {
        // Remove any CSS modifiers
        $that.removeClass('#{@key}');

        // Set the flash box content
        $('#topAlertBar').html('Please confirm your account by following the instructions sent to #{current_user.email}.  To resend your confirmation email, #{escape_javascript(link_to("click here", user_resend_confirmation_path(current_user), :class => "inlinelink", :method => :post, :remote => true))} #{escape_javascript(image_tag("ajaxOrange.gif", :class => "soft-hidden mls mbs"))}.');

        // Slides down the top alert bar after page load
        $('#topAlertBar, #alertBarOffset').slideDown("fast");

        // Shows & hides AJAX loading GIF when necessary
        $('#topAlertBar a').click(function() {
          $(document).bind('ajaxSend', function(e, request, options) {
            $("#topAlertBar img").show();
          });
          $(document).bind('ajaxComplete', function(e, request, options) {
            $(document).unbind('ajaxSend', 'ajaxComplete');
            $("#topAlertBar img").hide();
          });
        });

      });
    });


- elsif !flash.empty?
  - # User is confirmed
  - # and there ARE flash messages to show

  - [:error, :success, :notice].each do |key| 
    - unless flash[key].blank?
      - @msg = flash[key]
      - @key = key

  :javascript
    // Set the flash box content
    var $that = $('#topAlertBar');
    $that.html('#{@msg}').addClass('#{@key}').delay(250).slideDown("fast", function() {
      $(this).delay(2000).slideUp("fast");
    });

2 ответа

Решение

В итоге я выбрал другой подход, чем тот, который рекомендовал Джесси, но он все же помог мне подумать о способах рефакторинга кода. Вот конечный результат, который настолько СУХОЙ, насколько я мог его получить, не меняя полностью, как я его уже реализовал.

Надеюсь, это поможет кому-то еще, кто наткнется на этот вопрос в будущем.


В моем ApplicationHelper (это несколько изменено по сравнению с первоначальным вопросом, поэтому теперь оно работает для моих ошибок проверки, а также для обычных флэш-сообщений)

  def display_flash_messages
    if !flash.empty?
      [:error, :success, :notice, :warning].each do |key| 
        unless flash[key].blank?
          @flash_key = key
          if flash[key].kind_of?(Array) && flash[key].size > 1
            @flash_msg = flash[key].join(' & ')
          elsif flash[key].kind_of?(Array) && flash[key].size == 1
            @flash_msg = flash[key].first
          elsif flash[key].kind_of?(String)
            @flash_msg = flash[key]
          end
        end
      end
    end
    return
  end

В моем основном файле макета я просто делаю:

  %body
    - if signed_in?
      = render 'shared/top_alert_bar'

В верхнем файле панели предупреждений

= display_flash_messages

/ top alert area
#topAlertBar.shadow_medium.soft-hidden
- if !current_user.confirmed?
  #alertBarOffset.colordark.soft-hidden
    / placeholder for alert bar offset

- if flash.empty? && !current_user.confirmed?
  - # User has yet to confirm their account
  - # and there AREN'T any flash messages to show

  :javascript
    #{render('shared/js/confirm_user')}

- elsif !flash.empty?

  :javascript
    // Set the flash box content
    var $that = $('#topAlertBar');
    $that.html('#{@flash_msg}').addClass('#{@flash_key}').delay(250).slideDown("fast", function() {
      $(this).delay(4000).slideUp("fast", function () {
        // Remove any CSS modifiers
        $that.removeClass('#{@flash_key}');

        #{!current_user.confirmed? ? render('shared/js/confirm_user') : ""}

      });
    });

В частичном подтверждении verify_user

:plain
  $('#topAlertBar').html('Please confirm your account by following the instructions sent to #{current_user.email}.  To resend your confirmation email, #{escape_javascript(link_to('click here', user_resend_confirmation_path(current_user), :class => 'inlinelink', :method => :post, :remote => true))}. #{escape_javascript(image_tag('ajaxOrange.gif', :class => 'soft-hidden mls mbs'))}');

  $('#topAlertBar, #alertBarOffset').delay(250).slideDown('fast');

И наконец, я переместил это в мой основной файл js

/* ******************************** */
/* Top Alert Bar for Flash Messages */
/* ******************************** */
// Description: Shows & hides AJAX loading GIF when necessary
$('#topAlertBar a').click(function() {
  $(document).bind('ajaxSend', function(e, request, options) {
    $("#topAlertBar img").show();
  });
  $(document).bind('ajaxComplete', function(e, request, options) {
    $("#topAlertBar img").hide();
    $(document).unbind('ajaxSend', 'ajaxComplete');
  });

});

Зачем беспокоиться о различных состояниях подтверждения пользователя? Просто попросите ваш application_controller установить оповещение, если пользователь не подтвержден.

Во-вторых - переместите все jquery в application.js и запустите его на каждой странице - он должен сдвинуть ваш контент вниз, если он существует, иначе ничего не делать.

Наконец, возьмите помощник по флэш-памяти, как показано ниже: http://snippets.dzone.com/posts/show/6440 а затем назовите его в макете как

%head
  %titile
  =javascript_include_tag :all
  =yield(:header)
%body
  =display_flash
  =yield
Другие вопросы по тегам