Decorators

A Decorator is linked to a Model. The goal is to extend the behaviors of a model without touching it directly. A decorator is used for specific use cases in the application. Mostly for Presenters or Views.

Role of a Decorator

The goal is to keep models as light as possible and extend them with reusable Decorators.

Location

  • app/decorators/
  • Should be suffix with _decorator.rb

Structure of a Decorator

Dos

  • Wrap a model instance with view-related logic
  • Formating
  • Extend a Model to add business logic
  • Use decorators in Presenters. Then a Presenter should only be used in Views.
  • You can create multiple decorators per model because you might have different use cases for a particular model.
  • May call view helpers (include them).

Don'ts

  • Work on different models at the same time, in this case, you might need a Presenters or a Query Object.
  • Make it too big: create different decorators is needed.

Code

module Handbook
  # Responsible for theme presentation in school admin's back office
  class ThemeDecorator < Draper::Decorator

    include ActionView::Helpers
    include Backend::Handbook::CollapseHelpers

    delegate_all

    # Decorated articles associated to the Handbook::Theme
    # See Handbook::ArticleDecorator
    def children
      articles.includes(:translations, :curriculums).map(&:decorate)
    end

    # The Handbook::Theme does not have it's own activation status
    # Its activation status therefore depends on the activation status of its articles
    def activation_status
      content_tag(:span, activation_status_text, class: activation_status_class)
    end

    # Active articles associated to the Handbook::Theme in the current locale
    def active_children_count
      children.count(&:active?)
    end

    # Are there any active in the current locale articles with curriculums
    # in the Handbook::Theme associated articles?
    def any_active_children_targeted?
      return false unless active_children_count > 0
      children.select(&:active?).any?(&:targeted?)
    end

    # Returns a no description message of the Handbook::Theme description is missing
    # Returns a formatted description of the Handbook::Theme otherwise
    def formatted_description
      if description.empty?
        I18n.t('decorators.handbook_theme.no_description')
      else
        simple_format(description)
      end
    end

    private

    # Depends of the number of active in the current locale articles associated to the theme
    def activation_status_text
      I18n.t(
        'decorators.handbook_menu_items.activation_status',
        count: active_children_count
      )
    end

    def activation_status_class
      any_active_children? ? 'label label-success' : 'label label-default'
    end

    def any_active_children?
      active_children_count > 0
    end
  end
end

results matching ""

    No results matching ""