class MetaPresenter::Builder

Builds a presenter class for a controller and method

Attributes

action_name[R]

@return [String] Name of the controller's action to hook the presenter up to

controller[R]

@return [ActionController::Base, ActionMailer::Base] Controller that this presenter will delegate methods to

Public Class Methods

new(controller, action_name) click to toggle source

Creates a new Builder

@param [ActionController::Base, ActionMailer::Base] controller Controller that this presenter will delegate methods to @param [String] action_name Name of the controller's action to hook the presenter up to

# File lib/meta_presenter/builder.rb, line 18
def initialize(controller, action_name)
  @controller = controller
  @action_name = action_name
end

Public Instance Methods

presenter_base_dir() click to toggle source
# File lib/meta_presenter/builder.rb, line 55
def presenter_base_dir
  File.join(Rails.root, "app", "presenters")
end
presenter_class() click to toggle source

@return [Class] Class constant for the built MetaPresenter::Base presenter

# File lib/meta_presenter/builder.rb, line 42
def presenter_class
  # Try to find the presenter class (Not guaranteed,
  # for example if the presenter class wasn't defined
  # or if the file wasn't found)
  klass = nil
  ancestors.each do |klass_name|
    klass = presenter_class_for(klass_name)
    break if !klass.nil?
  end

  klass
end

Private Instance Methods

all_ancestors() click to toggle source
# File lib/meta_presenter/builder.rb, line 60
def all_ancestors
  controller.class.ancestors.select do |ancestor|
    if controller.class <= ActionController::Base
      ancestor <= ActionController::Base
    elsif controller.class <= ActionMailer::Base
      ancestor <= ActionMailer::Base
    else
      raise InvalidControllerError.new(controller)
    end
  end
end
ancestors() click to toggle source
# File lib/meta_presenter/builder.rb, line 101
def ancestors
  # Different ancestors depending on whether
  # we're dealing with a mailer or a controller
  list = if all_ancestors.map(&:to_s).include?("ActionMailer::Base")
    mailer_ancestors
  else
    controller_ancestors
  end

  # add a presenter class for our current action
  # to the front of the list
  presenter_class_name_for_current_action = "#{list.first}::#{action_name.camelcase}"
  list.unshift(presenter_class_name_for_current_action)
end
ancestors_until(until_class) { |klass| ... } click to toggle source

The list of ancestors is very long. Trim it down to just the length of the class we are looking for.

Takes an optional block method to transform the result with a map operation

# File lib/meta_presenter/builder.rb, line 121
def ancestors_until(until_class)
  # trim down the list
  ancestors_list = all_ancestors[0..all_ancestors.index(until_class)]

  # map to the fully qualified class name
  ancestors_list.map { |klass| yield(klass) }
end
controller_ancestors() click to toggle source
# File lib/meta_presenter/builder.rb, line 78
def controller_ancestors
  ancestors_until(ApplicationController) do |klass|
    klass.try(:name).try(:gsub, 'Controller', '')
  end
end
mailer_ancestors() click to toggle source
# File lib/meta_presenter/builder.rb, line 72
def mailer_ancestors
  ancestors_until(ApplicationMailer) do |klass|
    "Mailers::#{klass.name.gsub('Mailer', '')}"
  end
end
presenter_class_for(klass_name) click to toggle source
# File lib/meta_presenter/builder.rb, line 84
def presenter_class_for(klass_name)
  presenter_class_name = "::#{klass_name}Presenter"
  begin
    return presenter_class_name.constantize

  # No corresponding presenter class was found
  rescue NameError => e
    filename = "#{presenter_class_name.underscore}.rb"
    presenter_file_path = File.join(presenter_base_dir, filename)
    if File.exists?(presenter_file_path)
      raise FileExistsButPresenterNotDefinedError.new(presenter_class_name, presenter_file_path)
    else
      return nil
    end
  end
end