rails 4 application view helper可能的重构

时间:2014-02-25 03:14:03

标签: ruby-on-rails ruby helper

在三种不同的布局中,我必须使用三种不同的配置来显示社交链接。我想设置一些方法来处理这个,但我 感觉这个代码可以进一步优化。附件部分可以由social_links(["show_div","show_email"])调用,例如 从方法中触发各种配置。这有点矫枉过正吗?我的另一个想法是进一步打破这些,只包括 链接而不是HTML代码。

重构提示?优化?

在我的application_helper.rb文件中:

  # shared social links displayed in multiple layouts
  def social_links(view_options = nil)
    html=%(<ul class="social-links">)
    html+=%(<li>) + blog_link(view_options) + %(</li>)
    html+=%(<li>) + podcast_link(view_options) + %(</li>)
    html+=%(<li>) + twitter_link(view_options) + %(</li>)
    html+=%(<li>) + instagram_link(view_options) + %(</li>)
    html+=%(<li>) + facebook_link(view_options) + %(</li>)
    html+=%(<li>) + pinterest_link(view_options) + %(</li>)
    if view_options && view_options.include?("show_email")
      html+=%(<li>) + contact_us_link(view_options) + %(</li>)
    end
    html+=%(</ul>)
    raw(html.strip)
  end

  def twitter_link(view_options = nil)
    html=%(<a href="#{ENV['SOCIAL_TWITTER']}" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-twitter-square"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Twitter)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

  def instagram_link(view_options = nil)
    html=%(
      <a href="#{ENV['SOCIAL_INSTAGRAM']}" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-instagram"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Instagram)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

  def facebook_link(view_options = nil)
    html=%(
      <a href="#{ENV['SOCIAL_FACEBOOK']}" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-facebook-square"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Facebook)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

  def pinterest_link(view_options = nil)
    html=%(
      <a href="#{ENV['SOCIAL_PINTEREST']}" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-pinterest-square"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Pinterest)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

  def blog_link(view_options = nil)
    html=%(
      <a href="#{ENV['SOCIAL_BLOG']}" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-rss-square"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Blog)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

  def podcast_link(view_options = nil)
    html=%(
      <a href="#{ENV['SOCIAL_PODCAST']}" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-caret-square-o-right"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Podcast)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

  def contact_us_link(view_options = nil)
    html=%(
      <a href="/contact_us" target="_blank">)
    if view_options && view_options.include?("show_div")
      html+=%(<div>)
    end
    html+=%(<i class="fa fa-envelope"></i>)
    if view_options && view_options.include?("show_desc")
      html+=%(Contact)
    end
    if view_options && view_options.include?("show_div")
      html+=%(</div>)
    end
    html+=%(</a>)
    raw(html.strip)
  end

更新一项:部分方法

经过进一步的交谈和思考后,我将助手改为部分_social_links.html.slim

- social_twitter = "<i class='fa fa-twitter-square'></i>".html_safe
- social_instagram = "<i class='fa fa-instagram'></i>".html_safe
- social_facebook = "<i class='fa fa-facebook-square'></i>".html_safe
- social_pinterest = "<i class='fa fa-pinterest-square'></i>".html_safe
- social_rss = "<i class='fa fa-rss-square'></i>".html_safe
- social_podcast = "<i class='fa fa-caret-square-o-right'></i>".html_safe
- social_email = "<i class='fa fa-envelope'></i>".html_safe
ul[class="social-links"]
  li
    a[href="#{ENV['SOCIAL_TWITTER']}" target="_blank"]
      - if collection && collection.include?("show_div")
        div
          = social_twitter
      - else
        = social_twitter
      - if collection && collection.include?("show_desc")
        | Twitter
  li
    a[href="#{ENV['SOCIAL_INSTAGRAM']}" target="_blank"]
      - if collection && collection.include?("show_div")
        div
          = social_instagram
      - else
        = social_instagram
      - if collection && collection.include?("show_desc")
        | Instagram
  li
    a[href="#{ENV['SOCIAL_FACEBOOK']}" target="_blank"]
      - if collection && collection.include?("show_div")
        div
          = social_facebook
      - else
        = social_facebook
      - if collection && collection.include?("show_desc")
        | Facebook
  li
    a[href="#{ENV['SOCIAL_PINTEREST']}" target="_blank"]
      - if collection && collection.include?("show_div")
        div
          = social_pinterest
      - else
        = social_pinterest
      - if collection && collection.include?("show_desc")
        | Pinterest
  li
    a[href="#{ENV['SOCIAL_BLOG']}" target="_blank"]
      - if collection && collection.include?("show_div")
        div
          = social_rss
      - else
        = social_rss
      - if collection && collection.include?("show_desc")
        | Blog
  li
    a[href="#{ENV['SOCIAL_PODCAST']}" target="_blank"]
      - if collection && collection.include?("show_div")
        div
          = social_podcast
      - else
        = social_podcast
      - if collection && collection.include?("show_desc")
        | Podcast
  - if collection && collection.include?("show_email")
    li
      a[href="/contact_us" target="_blank"]
        - if collection && collection.include?("show_div")
          div
            = social_email
        - else
          = social_email
        - if collection && collection.include?("show_desc")
          | Contact

可以通过以下方式调用partial: render partial: "layouts/social_links", locals: { collection: ["show_div","show_email"]}render partial: "layouts/social_links", locals: { collection: nil}

更新二:OO方法建议

这可以称为:

social_links()
social_links(show_desc: true, show_list: %w{contact})
social_links(show_div: true, show_list: %w{contact})

在文件夹/ helpers / social_link中,我有一般助手:

module SocialLink
  module SocialLinkHelper
  # ****************************************************************************************************
  # ****************************************************************************************************
  DEFAULT_SOCIAL_PROVIDERS = %w{twitter facebook instagram pinterest blog podcast}

  def social_links(options={})
    content_tag :ul, class: "social-links" do
      provider_link(options)
    end
  end

  def provider_link(options={})
    social_providers = DEFAULT_SOCIAL_PROVIDERS
    social_providers = social_providers + options[:show_list] if options[:show_list]
    social_providers.each do |provider|
      klass = "SocialLink::SocialLinkClass::#{provider.titleize}Link".constantize
      link  = klass.new(options)
      concat link.generate
    end
  end

  # ****************************************************************************************************
  # ****************************************************************************************************
  end
end

在/ helpers / social_link文件夹中,我有我的控件类:

module SocialLink
  module SocialLinkClass

    class SocialBase < ActionView::Base
      include ActionView::Helpers::TagHelper

      def initialize(options)
        @show_div = options[:show_div] || nil
        @show_desc = options[:show_desc] || nil
      end

      def generate
        content_tag :li do
          content = content_tag(:i, nil, class: self.class.icon)
          content = content + self.class.description.titleize if @show_desc
          content = "<div>#{content}</div>" if @show_div
          link_to(content.html_safe, self.class.link)
        end
      end
    end

    # ****************************************************************************************************
    class ContactLink < SocialBase
      def self.link
        "/contact_us"
      end
      def self.description
        "contact"
      end
      def self.icon
        "fa fa-envelope"
      end
    end
    # ****************************************************************************************************
    class BlogLink < SocialBase
      def self.link
        ENV['SOCIAL_BLOG']
      end
      def self.description
        "blog"
      end
      def self.icon
        "fa fa-rss-square"
      end
    end
    # ****************************************************************************************************
    class PodcastLink < SocialBase
      def self.link
        ENV['SOCIAL_PODCAST']
      end
      def self.description
        "podcast"
      end
      def self.icon
        "fa fa-caret-square-o-right"
      end
    end
    # ****************************************************************************************************
    class PinterestLink < SocialBase
      def self.link
        ENV['SOCIAL_PINTEREST']
      end
      def self.description
        "pinterest"
      end
      def self.icon
        "fa fa-pinterest-square"
      end
    end
    # ****************************************************************************************************
    class InstagramLink < SocialBase
      def self.link
        ENV['SOCIAL_INSTAGRAM']
      end
      def self.description
        "instagram"
      end
      def self.icon
        "fa fa-instagram"
      end
    end
    # ****************************************************************************************************
    class TwitterLink < SocialBase
      def self.link
        ENV['SOCIAL_TWITTER']
      end
      def self.description
        "twitter"
      end
      def self.icon
        "fa fa-twitter-square"
      end
    end
    # ****************************************************************************************************
    class FacebookLink < SocialBase
      def self.link
        ENV['SOCIAL_FACEBOOK']
      end
      def self.description
        "facebook"
      end
      def self.icon
        "fa fa-facebook-square"
      end
    end
    # ****************************************************************************************************

  end
end

更新三:我的好友@drewtempelmeyer方法

文件:_social_link.html.erb

<%= social_icon service, collection %>
<% if show_desc?(collection) %>
  | <%= service.titleize %>
<% end %> 

档案:profile.html.erb

<%= render_social_link 'facebook', %w(show_div show_desc) %>

文件:social_helper.rb

module SocialHelper
  def render_social_link(service = 'facebook', collection = nil)
    render partial: 'shared/social_link', locals: {
      service: service, collection: collection
    }
  end

  def show_div?(collection)
    collection && collection.include?('show_div')
  end

  def show_desc?(collection)
    collection && collection.include?('show_desc')
  end

  def social_icon(service, collection)
    content = content_tag(:li, nil, class: "fa fa-#{service.downcase}")
    content = "<div>#{content}</div>" if show_div?(collection)
    content
  end
end

1 个答案:

答案 0 :(得分:2)

这将是在视图逻辑上应用OOP的一个很好的用例。部分也可以完成这项工作,但如果选择太多,它看起来会很混乱。

从一般助手social_links开始并没有错。助手只是为了帮助观点。

但是后来,你需要上课来完成详细的工作。

您调用帮助者的视图

<%= social_links show_div: 'foo' %>

一般助手

SOCIAL_PROVIDERS = ['Twitter', 'Facebook', 'GooglePlus']

def social_links(options)
  content_tag :ul do
    provider_link(options)
  end
end

def provider_links(options)
  SOCIAL_PROVIDERS.each do |provider|
    klass = "#{provider}Link".constantize
    link  = klass.new(options)
    concat link.generate
  end    
end

然后是课程

class SocialLink
  def self.link
    "#"
  end

  def initialize(options)
    @show_div = options.try(:show_div)
    @show_desc = options.try(:show_div)
  end

  def generate
    content_tag :li do
      concat main_link
      concat show_div_link if @show_div
      concat show_desc_link if @show_desc
    end
  end

  private
  def main_link
    # Your html
    # call self.class.link here
  end

  def show_div_link
    # You html
  end

  def show_desc_link
    # You html
  end
end

class TwitterLink < SocialLink
  def self.link
    ENV['SOCIAL_TWITTER']
  end
end

这些是演示代码,但您明白了