【问题标题】:DRYing up some Rails/HAML/jQuery view code干燥一些 Rails/HAML/jQuery 视图代码
【发布时间】:2011-04-01 13:44:27
【问题描述】:

我在屏幕顶部呈现一个警告栏作为部分,向用户显示成功/失败/通知闪存消息。

我终于让它适用于大多数场景,但代码本身在某些部分是重复的,我不确定如何更有效地拆分它,因为我对所有这些都比较陌生。我的目标是尽可能不重复自己,或者至少尽量减少重复次数。

例如,有没有办法将一些 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");
    });

【问题讨论】:

  • 顺便说一句,这个问题最初发布在codereview.stackexchange.com,但显然没有人真正去那里审查代码,所以我将它迁移回这里。

标签: jquery ruby-on-rails refactoring haml dry


【解决方案1】:

为什么要为用户确认的所有不同状态而烦恼?如果用户未得到确认,只需让您的 application_controller 设置一个闪光警报。

其次 -- 将所有 jquery 移动到 application.js 并在每个页面上运行它 -- 如果内容存在,它应该向下滑动您的内容,否则什么也不做。

最后,获取如下所示的 flash 助手:http://snippets.dzone.com/posts/show/6440,然后在您的布局中调用它

%head
  %titile
  =javascript_include_tag :all
  =yield(:header)
%body
  =display_flash
  =yield

【讨论】:

  • 如果我没有像这样在 HAML jQuery 代码中设置 Ruby 对象,这部分内容对我有用:$that.html('#{@msg}').addClass('#{@key}') ..但是,我不确定你的解决方案是否适合我这个原因。
  • 你不需要这样做。让 jquery 抓取内容(如果存在)
  • 感谢您的建议,杰西;今天早上他们帮助我动了脑筋。我最终做了一些不同的事情,因为我不想重新创建我已经拥有的系统。
【解决方案2】:

我最终采用了与 Jesse 推荐的方法不同的方法,但他仍然帮助我思考重构代码的方法。这是最终结果,在不完全改变我已经实现的方式的情况下,我可以得到它。

希望这将帮助其他人在未来偶然发现这个问题。


在我的 ApplicationHelper 中(对原始问题进行了一些修改,因此它现在适用于我的验证错误以及常规 flash 消息)

  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') : ""}

      });
    });

在确认用户部分

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

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多