Home > OS >  Rails text helpers - A, B, C and D
Rails text helpers - A, B, C and D

Time:04-05

I feel like this should exist, but I'm looking for a Rails helpers that handles listing a collection of items.

# Input and expected output
[1,2,3,4] # 1, 2, and 2 others.
[1,2,3] # 1, 2, and 3.
[1,2] # 1 and 2.
[1] # 1.

Does anything like this exist?

CodePudding user response:

Maybe this one?

[1,2,3].to_sentence
=> "1, 2 and 3"

CodePudding user response:

Archer answered the question, however my use case required a little more customization so I ended up (for better or worse) reinventing the wheel.

  sig do
    params(
        items: T::Array[T.untyped],
        count: Integer,
        renderer: T.nilable(T.proc.params(arg0: T.untyped).returns(String)),
        final_renderer:
          T.nilable(T.proc.params(arg0: T.untyped).returns(String)),
      )
      .returns(T.untyped)
  end
  def listicle(items, count: 3, renderer: nil, final_renderer: nil)
    SolidAssert.assert(items.size > 0, 'Must provide at least 1 item.')
    buffer = ''
    rendered_items =
      items.first(count).map { |item| renderer ? renderer.call(item) : item }
    if items.size <= count
      # Case: All items can be inlined.
      if rendered_items.size == 1
        buffer = rendered_items.join
      else
        items_before_and = rendered_items.first(rendered_items.size - 1)
        last_item = rendered_items.last
        buffer = items_before_and.join(', ')
        buffer << " and #{last_item}"
      end
    else
      # Case: There are too many items so we render an "and 1 other..." item.
      remaining_count = items.size - count
      final_item =
        if final_renderer
          final_renderer.call(remaining_count)
        else
          "#{ApplicationController.helpers.pluralize(remaining_count, 'other')}"
        end
      buffer = rendered_items.join(', ')
      buffer << " and #{final_item}"
    end
    buffer.html_safe
  end
  • Related