Search code examples
ruby-on-railsclasshelper

Rails helpers as a class


I am finding myself writing helpers to make my views very clean; however helpers don't naturally come as classes, just a collection of methods inside of a module. As a result, these methods don't share data like there would if initialized were called with params. So I end up passing around data multiple times. It's annoying. Is there a way to put there in a class that shares values?

Here's an example I am trying to dry up -- and yes, it's far from optimal code, please just focus on the issue I'm trying to sort through; I'd rather not waste time with making a perfect example. In the below, options are being passed in but but I end up passing them to additional methods, etc.

module Dashboard::DashboardHelper
    def menu_item(link_ref, options={})
        title           = options.fetch(:title,     "")
        details         = options.fetch(:details,   "")
        highlight       = options.fetch(:highlight,     false)
        icon            = options.fetch(:icon,      "")
        first           = options.fetch(:first,     false)
        subs            = options.fetch(:subs, [])
        link_item_class = (first) ? "m-t-30" : " "

        content_tag(:li, 
                    menu_link_label(link_ref,title,details,icon,highlight), 
                    class: link_item_class
        )
    end

    def menu_link_label(link_ref, title, details, icon, highlight)
        link_to(menu_labels(title,details), link_ref, class: "detailed") +
        icon_thumbnail(icon,highlight)
    end

    def menu_labels(title, details)
        content_tag(:span, title, class: "title") +
        content_tag(:span, details, class: "details")       
    end

    def icon_thumbnail(name, family, highlight=true)
        classes = (highlight) ? "bg-success icon-thumbnail" : "icon-thumbnail"
        content_tag(:span,icon(name, family), class: classes)
    end

    def icon(name)
        (name.present?) ? content_tag(:i, nil, class:"fas fa-#{name}") : ""
    end
end

Edit:

The options hash comes directly from the view usually in the below form:

<%= menu_item dashboard_root_path, 
    title: "Dashboard", 
    details: "12 New Updates", 
    icon: "fe:home",
    first: true,
    highlight: true
%>

Solution

  • There's nothing stopping you from having some classes on your own in e.g. app/view_helpers and using them in your views

    # app/view_helpers/menu.rb
    class Menu
      attr_accessor :options
      def initialize(options={})
        # do something with your options
        # self.options[:header] = options.fetch(:header, '')
      end
    
      def header
        # use your options here
        content_tag(:h1, options[:header])
      end
    end
    
    
    # some_controller.rb
    def index
      @menu = Menu.new
    end
    
    
    # index.html.erb
    <%= @menu.header %>