medcat/breadcrumb_trail

View on GitHub
lib/breadcrumb_trail/builder.rb

Summary

Maintainability
A
45 mins
Test Coverage
module BreadcrumbTrail

  # A Builder that is used by
  # {ActionController::HelperMethods#render_breadcrumbs}.  This should
  # be subclassed and implemented.
  #
  # @abstract
  class Builder

    # Initialize the builder.
    #
    # @param context [ActionView::Base] The base of the view being
    #   rendered.
    # @param breadcrumbs [Array<Breadcrumb>] The breadcrumbs to
    #   render.
    # @param options [Hash] The options for the builder.
    def initialize(context, breadcrumbs, options = {}, &block)
      @context = context
      @breadcrumbs = breadcrumbs
      @options = options
      @block = block
    end

    # Renders the breadcrumbs using the builder.  However, since this
    # is the base, it raises an error.
    #
    # @raise [NotImplementedError]
    # @return [String]
    def call
      raise NotImplementedError
    end

  end

  # Used along with a block given to the initializer, this renders
  # the breadcrumbs.
  class BlockBuilder < Builder

    # Creates a buffer, and iterates over every breadcrumb, yielding
    # the breadcrumb to the block given on initialization.
    #
    # @return [String]
    def call
      buffer = ActiveSupport::SafeBuffer.new
      @breadcrumbs.each do |breadcrumb|
        buffer << @block.call(breadcrumb.computed(@context))
      end

      buffer
    end
  end

  # Creates a structure of HTML elements to render the breadcrumbs.
  class HTMLBuilder < Builder

    include ActionView::Helpers

    # Renders the breadcrumbs in HTML tags.  If no options were
    # provided on initialization, it uses defaults.
    #
    # @option @options [String] :outer ("ol") The outer tag element
    #   to use.
    # @option @options [String] :inner ("li") The inner tag element
    #   to use.
    # @option @options [Hash] :outer_options (nil) The outer tag
    #   element attributes to use.  Things like `class="some-class"`
    #   are best placed here.
    # @option @options [Hash] :inner_options (nil) The inner tag
    #   element attributes to use.  Things like `class="some-class"`
    #   are best placed here.
    # @return [String]
    def call
      outer_tag = @options.fetch(:outer, "ol")
      inner_tag = @options.fetch(:inner, "li")
      outer = tag(outer_tag,
                  @options.fetch(:outer_options, nil),
                  true) if outer_tag
      inner = tag(inner_tag,
                  @options.fetch(:inner_options, nil),
                  true) if inner_tag

      buffer = ActiveSupport::SafeBuffer.new
      buffer.safe_concat(outer) if outer_tag

      @breadcrumbs.each do |breadcrumb|
        buffer.safe_concat(inner) if inner_tag
        buffer << link_to(breadcrumb.computed_name(@context),
                          breadcrumb.computed_path(@context),
                          breadcrumb.options)
        buffer.safe_concat("</#{inner_tag}>") if inner_tag
      end

      buffer.safe_concat("</#{outer_tag}>") if outer_tag
      buffer
    end

  end
end