Skip to content

Instantly share code, notes, and snippets.

@volontarian
Created June 4, 2012 14:10
Show Gist options
  • Save volontarian/2868636 to your computer and use it in GitHub Desktop.
Save volontarian/2868636 to your computer and use it in GitHub Desktop.
Layout presenter inheritance on Rails
class Presenter
def initialize(subject, options = {})
@subject = subject
init_haml_helpers
end
private
def method_missing(*args, &block)
@subject.send(*args, &block)
end
end
class ApplicationController < ActionController::Base
def self.layout_presenter(type, options = {})
@_layout_presenter_type = type
remove_possible_method(:_layout_presenter_type)
self.class_eval %{def _layout_presenter_type; #{@_layout_presenter_type.inspect} end}, __FILE__, __LINE__
end
def layout_presenter
unless @layout_presenter
type = nil
if respond_to?(:_layout_presenter_type) && _layout_presenter_type.present?
type = _layout_presenter_type
elsif _layout.present?
type = "View::#{_layout.classify}Layout"
else
raise NotImplementedError
# maybe ...
type = "View::Layout"
end
raise ArgumentError if type.blank?
@layout_presenter ||= PresenterFactory.create(type, self.view_context, request.format)
end
@layout_presenter
end
helper_method :layout_presenter
end
Module ApplicationHelper
include Haml::Helpers
...
end
class CommunitiesController < ApplicationController
layout 'community'
...
end
!!!
%html
= layout_presenter.head
%body
...
class PresenterFactory
def self.create(type, template, format, options = {})
#type = self.class.name.split('::').last.gsub('Factory', '')
namespace = nil
if format.to_sym == :mobile
namespace = 'Mob'
elsif format.to_sym == :facebook
namespace = 'Facebook'
elsif format.to_sym == :workflow
namespace = 'Workflow'
elsif format.to_sym == :html
namespace = 'Desktop'
end
raise NotImplementedError.new("Unexpected format #{format.inspect}") if namespace.blank?
eval("#{[namespace, type].join('::')}.new(template, options)")
end
end
class View::Layout < ::Presenter
def head(options = {})
render 'layouts/head', options
end
end
class Html::View::Layout < ::View::Layout
end
class Facebook::View::Layout < ::View::Layout
def head(options = {})
options.merge!(locals: {stylesheet: 'facebook'})
super(options)
end
end
class Html::View::CommunityLayout < ::Html::View::Layout
include ::View::CommunityLayout
end
class Facebook::View::CommunityLayout < ::Html::View::Layout
include ::View::CommunityLayout
end
module View::CommunityLayout
extend ActiveSupport::Concern
def format_overall_method
...
end
end
app/presenters/$format (e.g. html)
$domain (e.g. view)
app/presenters/$domain (e.g. view)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment