lib/masterview/extras/app/controllers/masterview_controller.rb in masterview-0.2.5 vs lib/masterview/extras/app/controllers/masterview_controller.rb in masterview-0.3.0
- old
+ new
@@ -1,89 +1,92 @@
#
# == MasterView Admin Controller
-#
+#
# The MasterviewController is a Rails controller that you can enable
# in your Rails application to provide administrative operations
# for the MasterView template engine.
-#
+#
# To enable or disable the admin controller, use the
# MasterView::Configuration setting +enable_admin_pages+
# to enable or disable its availability in your
# config/masterview/settngs.rb or a suitable environment
# settings file, according to your intended usage:
-#
+#
# config.enable_admin_pages = true
-#
+#
# When enabled, the MasterView admin controller is accessable
# in your application at the address:
-#
+#
# http://yourapp.foo/masterview
-#
-# The controller places its stylesheets in a +masterview+ subdirectory
+#
+# The controller places its stylesheets in a +masterview+ subdirectory
# in your rails stylesheets directory (app/stylesheets/masterview).
-#
-# The MasterView admin controller is primarily a developer facility;
+#
+# The MasterView admin controller is primarily a developer facility;
# it is not generally appropriate for end-users of your rails application.
# If you enable this facility in your production environment,
# you should consider restricting access to authorized users.
#
#--
# ISSUE: we need to work through scenario of how mv admin controller fits
# into overall scheme of one's rails application. How/when would developer
# integrate stylesheets and layout into their overal app look?
# How/when would access restriction actually be hooked up?
# Standard technique is to do something along the lines of using
-# a before_filter which invokes things like :check_authentication
+# a before_filter which invokes things like :check_authentication
# and :check_authorization services in the app framework
# (or, say, predicate can_access? or has_permission? or...].
-# But... this whole area of user authentication and authorization
+# But... this whole area of user authentication and authorization
# has no specific conventions in the Rails ecosystem yet,
# so we really can't make any assumptions yet about any particular
# approach that MasterviewController itself could hook into.
# We'll have to leave this as an exercise for the user and give
# them tips on how to make it happen.
# [DJL 17-Jun-2006]
#++
-#
+#
require 'masterview/extras/sample_templates'
class MasterviewController < ApplicationController
- include MasterView::DefaultGenerateMIOFilter
+ include MasterView::MIO::DefaultGenerateMIOFilter
before_filter :check_authorization, :except => [ :access_not_allowed ]
- ENABLE_ADMIN_LAYOUT = false #:nodoc: #UNDER CONSTRUCTION - fine idea, but doesn't work yet [DJL 03-Jun-2006]
+ ###layout 'masterview_admin'
- # Describe the MasterView configuration option settings
- def configuration
- if ENABLE_ADMIN_LAYOUT
- smart_render_with_layout('masterview/admin/configuration', 'masterview_admin')
- else
- #ugly, but keep this version
- aint_got_no_layout_backstop = '<div style="padding-top: 6px;">(back to <a href=".">Admin home</a>)</div>'
- config_html = MasterView::Info.to_html( :postscript => aint_got_no_layout_backstop )
- render :text => config_html
- end
- end
-
+ MV_ADMIN_INSTALL_DIR = File.expand_path( File.join(File.dirname(__FILE__), '../..') ) #:nodoc:
+ #CONTEXT_REF_VIEW = 'app/views'
+ #CONTEXT_REF_LAYOUT = 'app/views/layout'
+ FILE_LOC_APP = 'app' #:nodoc:
+ FILE_LOC_MV = 'mv' #:nodoc:
+
def index
redirect_to :action => :list
end
# List the templates in the application and their status.
- # Provide operations to force rebuild (reparse and regenerate)
+ # Provide operations to force rebuild (reparse and regenerate)
# of specific templates or all templates and
# create utility to ...mumble...
- #
+ #
def list
template_specs, content_hash = MasterView::TemplateSpec.scan
@template_specs_sorted = template_specs.sort
- smart_render 'masterview/admin/list'
+ masterview_render_with_layout( 'masterview/admin/list', 'masterview_admin' )
end
+ # Describe the MasterView configuration option settings
+ def configuration
+ masterview_render_with_layout( 'masterview/admin/configuration', 'masterview_admin_config' )
+ end
+
+ def directives
+ masterview_render_with_layout( 'masterview/admin/directives', 'masterview_admin_config' )
+ end
+
def features
- smart_render 'masterview/admin/features'
+ masterview_render_with_layout( 'masterview/admin/features', 'masterview_admin_config' )
end
# Rebuild all templates in the application.
# Invoked from the main masterview admin page.
def rebuild_all
@@ -101,11 +104,11 @@
end
# Rebuild a specific template.
# Invoked from the main masterview admin page.
def rebuild
- path = params[:id]
+ path = params[:file]
template_specs, content_hash = MasterView::TemplateSpec.scan
template_spec = template_specs[path]
raise 'Template '+path+' not found' unless template_spec
if template_spec.rebuild_template(content_hash, :write_to_file => true)
flash[:notice] = 'File '+path+' updated'
@@ -118,11 +121,11 @@
# Create a new, empty template.
# Invoked from the main masterview admin page.
def create
if @request.post?
action_to_create = params[:action_name]
- src_file = params[:id]
+ src_file = params[:file]
empty_file_path = find_path('app/views/masterview/admin/empty.rhtml')
empty_insert_erb = File.readlines(empty_file_path).join
dst_file = MasterView::TemplateSpec.create_empty_shell_for_action(src_file, action_to_create, empty_insert_erb, :write_to_file => true)
@@ -134,11 +137,11 @@
end
# View the generated rhtml
def view_rhtml
raise "View RHTML is disabled. Edit your config/masterview/settings.rb (or config/masterview/environments/xxxx.rb) file and set config.enable_view_rhtml = true. Restart application for change to take effect." unless MasterView::EnableMasterViewAdminViewRHTML
- @rhtml_file = params[:id]
+ @rhtml_file = params[:file]
raise "RHTML file not specified" unless @rhtml_file
f = MasterView::IOMgr.erb.path(@rhtml_file)
raise "RHTML file ("+@rhtml_file+") not found. Maybe automatic parsing is disabled. You may invoke parsing manually by using rake mv:parse" unless f.exist?
@rhtml_content = f.read
smart_render 'masterview/admin/view_rhtml'
@@ -147,26 +150,30 @@
# interact, test template src, view results
def interact
@results = []
@src = params[:src]
if @src
- sh_mio = MasterView::StringHashMIOTree.new({}, MasterView::LoadedConfiguration.generated_file_default_extension )
-
- src_with_default_gen = add_default_gen_if_needed(@src) # apply a default generate
- MasterView::Parser.parse( src_with_default_gen, { :output_mio_tree => sh_mio, :omit_comment => true, :template_pathname => 'YOUR_TEMPLATE_PATH_HERE' } )
- @results = sh_mio.string_hash.sort.collect do |file,rhtml|
- os = OpenStruct.new
- os.file = file
- os.rhtml = rhtml
- os
+ begin
+ sh_mio = MasterView::MIO::StringHashMIOTree.new({}, MasterView::ConfigSettings.generated_file_default_extension )
+
+ src_with_default_gen = add_default_gen_if_needed(@src) # apply a default generate
+ MasterView::Parser.parse( src_with_default_gen, { :output_mio_tree => sh_mio, :omit_comment => true, :template_pathname => 'YOUR_TEMPLATE_PATH_HERE', :rescue_exceptions => false } )
+ @results = sh_mio.string_hash.sort.collect do |file,rhtml|
+ os = OpenStruct.new
+ os.file = file
+ os.rhtml = rhtml
+ os
+ end
+ rescue REXML::ParseException => e
+ @error_message = e.to_s
end
end
smart_render 'masterview/admin/interact'
end
def access_not_allowed #:nodoc:
- render :text => '<p>We\'re sorry, but the page you have requested is only available to authorized users.</p>',
+ render :text => '<p>We\'re sorry, but the page you have requested is only available to authorized users.</p>',
:status => 500
end
protected
@@ -184,58 +191,78 @@
if ! allow_access?
redirect_to :action => :access_not_allowed
end
end
- private
+ private
# checks app path first for views and files, then falls back to files in MV
def find_path(path)
- local_path = File.join(RAILS_ROOT, path)
- mv_path = File.join(File.dirname(__FILE__), '../..', path)
- working_path = (File.exist?(local_path)) ? local_path : mv_path
+ app_path = File.join(RAILS_ROOT, path)
+ mv_path = File.join(MV_ADMIN_INSTALL_DIR, path)
+ working_path = (File.exist?(app_path)) ? app_path : mv_path
end
# render local template file if exists otherwise render file from mv
def smart_render(short_path)
- local_path = File.join(RAILS_ROOT, 'app/views', short_path)+'.rhtml'
- if File.exist?(local_path)
+ template_path, template_loc = resolve_relative_path( short_path, 'app/views' )
+ if template_loc == FILE_LOC_APP
render :template => short_path
else
- mv_path = File.join(File.dirname(__FILE__), '../../app/views', short_path)+'.rhtml'
- MasterView::Log.debug { 'mv_path='+mv_path }
- render :file => mv_path
+ MasterView::Log.debug { 'render admin template from mv_path='+template_path }
+ render :file => template_path
end
end
# render local template file if exists otherwise render file from mv
- def smart_render_with_layout(short_path, layout) #:nodoc: #UNDER CONSTRUCTION
- #DOESN'T WORK YET - we get the right path, but need a way into template rendering
- # (usual path through rails bolts in assumption of app/views rel path)
- # [DJL 03-Jul-2006]
- local_path = File.join(RAILS_ROOT, 'app/views', short_path)+'.rhtml'
- if File.exist?(local_path)
- render :template => short_path, :layout => smart_layout_path(layout)
+ def masterview_render_with_layout(short_path, layout) #:nodoc:
+ template_path, template_loc = resolve_relative_path( short_path, 'app/views' )
+ layout_path, layout_loc = resolve_relative_path( layout, 'app/views/layouts' )
+ if (template_loc == FILE_LOC_APP) && (layout_loc == FILE_LOC_APP)
+ # app has customized both the admin page view and its layout
+ render :template => short_path, :layout => layout
else
- mv_path = File.join(File.dirname(__FILE__), '../../app/views', short_path)+'.rhtml'
- MasterView::Log.debug { 'mv_path='+mv_path }
- render :file => mv_path, :layout => smart_layout_path(layout)
+ # template or layout or both use std masterview
+ MasterView::Log.debug { 'render admin template from mv_path='+template_path }
+ MasterView::Log.debug { 'render admin layout from mv_path='+layout_path } if layout_loc == FILE_LOC_MV
+ masterview_render_file_with_layout( template_path, layout_path )
end
end
- def smart_layout_path(short_path) #:nodoc: #UNDER CONSTRUCTION
- local_path = File.join(RAILS_ROOT, 'app/views/layouts', short_path)+'.rhtml'
- if File.exist?(local_path)
- short_path
- else
- mv_layouts_dir_path = File.expand_path( File.join(File.dirname(__FILE__), '../../app/views/layouts') )
- mv_path = File.join(mv_layouts_dir_path, short_path)+'.rhtml'
- if File.exist?(mv_path)
- MasterView::Log.debug { 'admin layout mv_path='+mv_path }
- else
- MasterView::Log.error { '***BAD ADMIN PAGE LAYOUT REF: mv_path='+mv_path }
- end
- mv_path
+ # Resolve a relative reference within the Rails application
+ # or to the masterview installation directory.
+ # Answer the full_path and a location indicator ('app' or 'mv')
+ def resolve_relative_path( short_path, context_ref='app/views', file_ext='.rhtml' )
+
+ file_ref = "#{short_path}#{file_ext}"
+
+ # resolve to rails app/views if present to allow app customization
+ app_path = File.join(RAILS_ROOT, context_ref, file_ref)
+ return [ app_path, FILE_LOC_APP ] if File.exist?(app_path)
+
+ # resolve to standard masterview view template if not overridden
+ mv_path = File.join(MV_ADMIN_INSTALL_DIR, context_ref, file_ref)
+ if ! File.exist?(mv_path)
+ MasterView::Log.error { '***NO SUCH MV ADMIN FILE: mv_path='+mv_path }
end
+ return [ mv_path, FILE_LOC_MV ]
end
+end
+
+# patch a special version of template rendering into ActionController::Base
+# standard layout rendering is bolted down to app/views/layout context
+module ActionController #:nodoc:
+ class Base #:nodoc:
+ def masterview_render_file_with_layout( template_path, layout_path, local_assigns={} )
+ # Implementation based on ActionController::Layout#render_with_a_layout
+ use_full_path = false #we already have full path, we don't want rails template_base prefixed
+ add_variables_to_assigns
+ content_for_layout = @template.render_file(template_path, use_full_path, local_assigns)
+ # following was needed in ActionController::Layout because of the way it does its overrides
+ #erase_render_results #??do we need to do this?? Is there any downside to doing so??!
+ #add_variables_to_assigns
+ @template.instance_variable_set('@content_for_layout', content_for_layout)
+ render_text(@template.render_file(layout_path, use_full_path, local_assigns))
+ end
+ end
end