Skip to content

Instantly share code, notes, and snippets.

@rossnelson
Created January 29, 2012 02:12
Show Gist options
  • Save rossnelson/1696783 to your computer and use it in GitHub Desktop.
Save rossnelson/1696783 to your computer and use it in GitHub Desktop.
Locomotive's multi site magic
module Admin
class RenderingController < ActionController::Base
include Locomotive::Routing::SiteDispatcher
include Locomotive::Render
before_filter :require_site
before_filter :authenticate_admin!, :only => [:edit]
before_filter :validate_site_membership, :only => [:edit]
def show
render_locomotive_page
end
def edit
@editing = true
render_locomotive_page
end
end
end
module Locomotive
module Render
extend ActiveSupport::Concern
module InstanceMethods
protected
def render_locomotive_page
if request.fullpath =~ /^\/admin\//
render :template => '/admin/errors/404', :layout => '/admin/layouts/box', :status => :not_found
else
@page = locomotive_page
redirect_to(@page.redirect_url) and return if @page.present? && @page.redirect?
render_no_page_error and return if @page.nil?
output = @page.render(locomotive_context)
self.prepare_and_set_response(output)
end
end
def render_no_page_error
render :template => '/admin/errors/no_page', :layout => false
end
def locomotive_page
path = (params[:path] || request.fullpath).clone # TODO: params[:path] is more consistent
path = path.split('?').first # take everything before the query string or the lookup fails
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension
path.gsub!(/^\//, '') # remove the leading slash
path = 'index' if path.blank?
if path != 'index'
dirname = File.dirname(path).gsub(/^\.$/, '') # also look for templatized page path
path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')]
end
if page = current_site.pages.any_in(:fullpath => [*path]).first
if not page.published? and current_admin.nil?
page = nil
else
if page.templatized?
@content_instance = page.content_type.contents.where(:_slug => File.basename(path.first)).first
if @content_instance.nil? || (!@content_instance.visible? && current_admin.nil?) # content instance not found or not visible
page = nil
end
end
end
end
page || not_found_page
end
def locomotive_context
assigns = {
'site' => current_site,
'page' => @page,
'asset_collections' => Locomotive::Liquid::Drops::AssetCollections.new, # depracated, will be removed shortly
'contents' => Locomotive::Liquid::Drops::Contents.new,
'current_page' => self.params[:page],
'params' => self.params,
'path' => request.path,
'url' => request.url,
'now' => Time.now.utc,
'today' => Date.today
}
assigns.merge!(Locomotive.config.context_assign_extensions)
assigns.merge!(flash.stringify_keys) # data from api
if @page.templatized? # add instance from content type
assigns['content_instance'] = @content_instance
assigns[@page.content_type.slug.singularize] = @content_instance # just here to help to write readable liquid code
end
registers = {
:controller => self,
:site => current_site,
:page => @page,
:inline_editor => self.editing_page?,
:current_admin => current_admin
}
::Liquid::Context.new({}, assigns, registers)
end
def prepare_and_set_response(output)
flash.discard
response.headers['Content-Type'] = 'text/html; charset=utf-8'
if @page.with_cache?
fresh_when :etag => @page, :last_modified => @page.updated_at.utc, :public => true
if @page.cache_strategy != 'simple' # varnish
response.cache_control[:max_age] = @page.cache_strategy
end
end
render :text => output, :layout => false, :status => page_status unless performed?
end
def not_found_page
current_site.pages.not_found.published.first
end
def editing_page?
@editing
end
def page_status
@page.not_found? ? :not_found : :ok
end
end
end
end
module Locomotive
module Routing
module SiteDispatcher
extend ActiveSupport::Concern
included do
if self.respond_to?(:before_filter)
before_filter :fetch_site
helper_method :current_site
end
end
module InstanceMethods
protected
def fetch_site
Locomotive.log "[fetch site] host = #{request.host} / #{request.env['HTTP_HOST']}"
if Locomotive.config.multi_sites?
@current_site ||= Site.match_domain(request.host).first
else
@current_site ||= Site.first
end
end
def current_site
@current_site || fetch_site
end
def require_site
return true if current_site
redirect_to admin_installation_url and return false if Account.count == 0 || Site.count == 0
render_no_site_error and return false
end
def render_no_site_error
render :template => '/admin/errors/no_site', :layout => false, :status => :not_found
end
def validate_site_membership
return true if current_site.present? && current_site.accounts.include?(current_admin)
sign_out(current_admin)
flash[:alert] = I18n.t(:no_membership, :scope => [:devise, :failure, :admin])
redirect_to new_admin_session_url and return false
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment