Class: MasterView::Initializer

Inherits:
Object
  • Object
show all
Defined in:
lib/masterview/initializer.rb

Overview

The Initializer is responsible for processing the MasterView configuration.

In a Rails application using the MasterView facilities, the Initializer is run automatically during rails startup when the plugin is loaded. No special action is required by the application.

To customize the MasterView configuration, provide config settings files in your application’s config directory, setting standard settings in config/masterview/settings.rb and optionally setting environment-specific values in config/masterview/environments/{environment}.rb. The settings files are executed with the config variable initialized to the current configuration. This is the standard technique for a Rails application.

An application using the MasterView facilities outside the Rails context must run the MasterView::Initializer during its application startup.

It can be run as a simple command that uses the default configuration:

require 'masterview/initializer'
MasterView::Initializer.run

or more simply just load MasterView:

require 'masterview'

In order to customize the MasterView configuration outside the Rails context, you must explicitly provide a basic Configuration to the Initializer which specifies the root location of the application and the paths to the template directories if the default locations are not appropriate. Configuration settings can be set directly or provided through config settings file by specifying the config_dir_path to the application’s setttings files.

require 'masterview/initializer'
config = MasterView::Configuration( :app_root_path = '/path/to/my/app' )
config.environment = 'production'
config.config_dir_path = 'masterview/config'
#... additional settings will be loaded from the config dir...
Masterview::Initializer( :process, config )

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Initializer

Create a new Initializer instance that references the given Configuration instance.



881
882
883
# File 'lib/masterview/initializer.rb', line 881

def initialize(config) #:nodoc:
  @configuration = config
end

Instance Attribute Details

#configurationObject (readonly)

The Configuration instance used by this Initializer instance.



859
860
861
# File 'lib/masterview/initializer.rb', line 859

def configuration
  @configuration
end

Class Method Details

.run(command = :process, configuration = Configuration.new) ⇒ Object

Runs the initializer. By default, this will invoke the #process method, which simply executes all of the initialization routines. Alternately, you can specify explicitly which initialization routine you want:

MasterView::Initializer.run(:initialize_configuration)

This is useful if you only want the config settings initialized, without incurring the overhead of completely loading the entire component.



870
871
872
873
874
875
876
877
# File 'lib/masterview/initializer.rb', line 870

def self.run(command = :process, configuration = Configuration.new)
  if block_given?
    yield configuration
  end
  initializer = new(configuration)
  initializer.send(command)
  initializer
end

Instance Method Details

#after_initializeObject

Fires the user-supplied after_initialize block (Configuration#after_initialize)



1190
1191
1192
# File 'lib/masterview/initializer.rb', line 1190

def after_initialize #:nodoc:
  configuration.after_initialize_block.call if configuration.after_initialize_block
end

#auto_copy_at_startupObject

:nodoc:



1156
1157
1158
# File 'lib/masterview/initializer.rb', line 1156

def auto_copy_at_startup #:nodoc:
  MasterView::AutoCopy.copy_all_updated_files
end

#complete_plugin_installationObject

Complete installation of masterview after its own code has been loaded



1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
# File 'lib/masterview/initializer.rb', line 1029

def complete_plugin_installation #:nodoc:
  #?? return if MasterView.const_defined?(:Initialized) ??
  MasterView::DirectiveRegistry.register_default_namespaces(
                                    configuration.namespace_prefix,
                                    configuration.namespace_prefix_extensions )
  initialize_logger
  initialize_mio
  set_rexml_parser_class
  initialize_auto_copy_files
  #Back out experiment: causes load order problems
  ##load_directives  # held off on this until logger is installed
  install_in_rails
  # mark the module as fully loaded and configured
  MasterView.const_set('Initialized', true)
  after_initialize  # callback to client's afer_initialize block
end

#enable_mv_admin_pagesObject

install the MasterviewController to support masterview admin pages in the site



1140
1141
1142
1143
# File 'lib/masterview/initializer.rb', line 1140

def enable_mv_admin_pages #:nodoc:
  return if ! configuration.enable_admin_pages  #MasterView::EnableMasterViewAdminPages
  require 'masterview/extras/init_mv_admin_pages'
end

#enable_rails_erb_directObject

:nodoc:



1179
1180
1181
1182
1183
1184
1185
1186
1187
# File 'lib/masterview/initializer.rb', line 1179

def enable_rails_erb_direct #:nodoc:
  unless configuration.generate_rhtml_files
    # if not generating rhtml the read erb directly from masterview
    MasterView::Log.info { 'Adding hooks to enable Rails to read erb directly from MasterView' }
    require 'masterview/rails_ext/action_view_erb_direct' #:nodoc:
    require 'masterview/rails_ext/action_controller_erb_direct' #:nodoc:
    MasterView::LoadedFeatures[:rails_erb_mv_direct] = true
  end
end

#enable_reparse_changed_templatesObject

– DBC-style notation per DbC - rubydbc-0.1 (Andy Hunt’s Design by Contract) pre( MasterView::ParseMasterViewTemplatesAtStartup ) pre( MasterView::ReparseChangedMasterViewTemplates ) pre( defined?(ActionController) && ActionController::Base.perform_caching ) ++



1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
# File 'lib/masterview/initializer.rb', line 1166

def enable_reparse_changed_templates  #:nodoc:
  if configuration.reparse_changed_masterview_templates #MasterView::ReparseChangedMasterViewTemplates
    # if not caching then check for masterview updates on every request
    # DBC-style notation per DbC - rubydbc-0.1 (Andy Hunt's Design by Contract)
    #pre( MasterView::ParseMasterViewTemplatesAtStartup )
    #pre( defined?(ActionController) && ActionController::Base.perform_caching )
    require 'masterview/extras/watcher' #:nodoc:
    MasterView::Log.info { 'Adding hook to allow MasterView to check for templates that have changed when processing a request' }
    require 'masterview/rails_ext/action_controller_reparse_checking' #:nodoc:
    MasterView::LoadedFeatures[:rails_reparse_checking] = true
  end
end

#ensure_valid_settingsObject

ensure that the requested configuration settings are consistent and valid before we actually install anything. Normalize representations as needed.



942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
# File 'lib/masterview/initializer.rb', line 942

def ensure_valid_settings #:nodoc:

  config = configuration

  #??config.root_path = File.expand_path(config.root_path) if config.root_path  #?? ensure bolted down firmly?

  # ensure that the directive load path entries are clean and available
  if not config.directive_load_path.empty?
    STDOUT.puts "###DEBUG: cleaning directive_load_path #{config.directive_load_path.inspect}" if DEBUG_DIRECTIVE_PATH
    clean_path = DirectiveLoadPath.clean_path( config.directive_load_path, :dup_policy => :use_latest ) { | ex |
      # record validation error from a path entry and press on
      # just note the problem and let initializer report it later
      config.initialization_messages << [ :error, ex.message ]
    }
    config.directive_load_path = clean_path
    STDOUT.puts "###DEBUG: CLEANED directive_load_path #{config.directive_load_path.inspect}" if DEBUG_DIRECTIVE_PATH
  end

  # template source and generation options
  if config.on_rails?
    #TODO: ensure that the config.template_dst_dir_path is
    # in the RAILS_ROOT/app/views directory
    # (ActionController::Base.view_root)
    # Otherwise all the fine rails view template stuff doesn't work
  end

  # Rails application options
  if config.on_rails?
    # ensure we don't activate runtime reparsing if we didn't autoparse at startup
    # (?overzealous?  But this what we're currently asserting as the intended behavior in the docs)
    if not config.parse_masterview_templates_at_startup
      config.reparse_changed_masterview_templates = false
    end
  #else
  #  self.reparse_changed_masterview_templates = false  # not supported
  end

end

#initialize_auto_copy_filesObject

Initialize the auto_copy_files MasterView I/O and AutoCopy setup



1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
# File 'lib/masterview/initializer.rb', line 1082

def initialize_auto_copy_files
  require 'masterview/extras/auto_copy'
  auto_copy_file_entries = configuration.auto_copy_file_entries
  if auto_copy_file_entries
    auto_copy_file_entries.each do |entry|
      if entry[:source] && entry[:destination]
        sourceMIO = MasterView::MIO::FileMIOTree.new(entry[:source])
        destMIO = MasterView::MIO::FileMIOTree.new(entry[:destination])
        extensions = entry[:extensions] || []
        filename_patterns = extensions.collect{ |ext| "*.#{ext.to_s}" }
        filename_patterns = ['*'] if filename_patterns.empty?
        filename_pattern_for_log = (filename_patterns.empty?) ? '*' : filename_patterns.join(',')
        MasterView::AutoCopy.register(sourceMIO, destMIO, filename_patterns)
        MasterView::Log.info{ "Auto copying files from #{entry[:source]} to #{entry[:destination]} with filter #{filename_patterns.join(',')}" }
      else
        MasterView::Log.error{ 'config.auto_copy_file_entries entry is missing required :source or :destination values, will be ignored. entry='+entry.inspect }
      end
    end
  end
end

#initialize_configurationObject

Load the Masterview configuration settings. Does not load and configure the template engine.

Intended for use in testing.



897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
# File 'lib/masterview/initializer.rb', line 897

def initialize_configuration
  #?? return if MasterView.const_defined?(:ConfigSettings) ??
  #ISSUE: support format_datetime option on the logger settings?? [DJL 30-Jul-2006]
  configuration.initialization_messages << [ :info,
                  "Initializing MasterView configuration (#{DateTime.now.strftime('%Y-%m-%d %H:%M')})" ]
  configuration.initialization_messages << [ :info,
                  "Program name = #{$PROGRAM_NAME}" ] # log the program that is starting the session
  load_config_settings
  ensure_valid_settings
  install_config_settings
  # make a final check for running_rails? (in case config settings changed scripts spec)
  configuration.decide_if_running_rails
  # keep a permananent record of how we got started
  configuration.freeze
  MasterView.const_set('ConfigSettings', configuration)
end

#initialize_loggerObject

Initialize MasterView::Log with a logger which emits to std output, default DEBUG level



1047
1048
1049
1050
1051
1052
1053
1054
# File 'lib/masterview/initializer.rb', line 1047

def initialize_logger #:nodoc:
  #?return if defined?(Log)
  require 'masterview/extras/init_logger'
  # release any queued-up initialization messages yearning to be free
  configuration.initialization_messages.each { | msg_level, msg |
    Log.send msg_level, msg
  }
end

#initialize_mioObject

Initialize the MasterView I/O subsystem



1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
# File 'lib/masterview/initializer.rb', line 1057

def initialize_mio
  config = configuration
  MasterView.const_set('DefaultSerializer', TemplateProcessing::MIOSerializer)
  # all root_path directory anchor points for I/O are expanded absolute paths
  io_mgr = MIO::MIOTrees.new
  template_extension = File.extname( config.template_filename_pattern )
  io_mgr.template = MIO::FileMIOTree.new( config.template_src_dir_path, template_extension,
                      :escape_erb => DefaultParserOptions[:escape_erb],  # use DefaultParserOptions since already has config merged
                      :tidy => DefaultParserOptions[:tidy],
                      :default_generate => DefaultParserOptions[:default_generate],
                      #TODO: expose the following in Configuration.default_parser_options and document
                      :caching => false,
                      :logging => true )

  if config.generate_rhtml_files
    io_mgr.erb = MIO::FileMIOTree.new( config.template_dst_dir_path, config.generated_file_default_extension, :logging => true)
  else
    io_mgr.erb = MIO::RailsErbCacheMIOTree.new( config.generated_file_default_extension, :logging => true)
  end
  io_mgr.backup = MIO::FileMIOTree.new( config.rebuild_backups_tmp_dir_path ) if config.rebuild_backups_tmp_dir_path
  MasterView.const_set('IOMgr', io_mgr)
  MasterView::LoadedFeatures[:tidy_template_read] = config.default_parser_options[:tidy]
end

#install_config_settingsObject

Install the configuration settings



982
983
984
985
# File 'lib/masterview/initializer.rb', line 982

def install_config_settings #:nodoc:
  set_module_constants
  DirectiveLoadPath.default_path_specs = configuration.directive_load_path  # does clone before freezing config
end

#install_in_railsObject

:nodoc:



1129
1130
1131
1132
1133
1134
1135
1136
1137
# File 'lib/masterview/initializer.rb', line 1129

def install_in_rails #:nodoc:
  return if ! configuration.on_rails?
  enable_mv_admin_pages
  parse_templates_at_startup
  auto_copy_at_startup
  enable_reparse_changed_templates
  enable_rails_erb_direct
  MasterView::Log.info{  'MasterView plugin initialized - Version '+MasterView::VERSION::STRING }
end

#load_app_settingsObject

Loads application config settings.



922
923
924
# File 'lib/masterview/initializer.rb', line 922

def load_app_settings #:nodoc:
  load_settings_file(configuration.app_settings_path)
end

#load_config_settingsObject

Load configuration settings from {config.config_dir_path}/settings.rb and {config.config_dir_path}/environments/{config.environment}.rb.



916
917
918
919
# File 'lib/masterview/initializer.rb', line 916

def load_config_settings #:nodoc:
  load_app_settings
  load_environment_settings
end

#load_directivesObject

NOTE: not currently used - caused problems during startup, so reverted to original scheme where loading is triggered on demand by template parsing

SJL 20-Sep-2006


1123
1124
1125
1126
1127
# File 'lib/masterview/initializer.rb', line 1123

def load_directives #:nodoc:
  # get the directives loaded prior to firing up any template parsing
  return if ! configuration.on_rails?  #ISSUE: causes problem for test cases; is this ever a good idea??
  MasterView::DirectiveRegistry.current.process_directives_load_path( configuration.directive_load_path )
end

#load_environment_settingsObject

Loads config settings for the environment specified by Configuration#environment_path, which is typically one of development, testing, or production.



929
930
931
# File 'lib/masterview/initializer.rb', line 929

def load_environment_settings #:nodoc:
  load_settings_file(configuration.environment_settings_path)
end

#load_pluginObject

Load the masterview code



1024
1025
1026
# File 'lib/masterview/initializer.rb', line 1024

def load_plugin #:nodoc:
  require 'masterview' #:nodoc:
end

#load_settings_file(config_file_path) ⇒ Object

Loads MasterView config settings from the specified config file.



934
935
936
937
938
# File 'lib/masterview/initializer.rb', line 934

def load_settings_file(config_file_path) #:nodoc:
  return if not (config_file_path && File.file?(config_file_path))
  config = configuration  # define config var in the binding context of the settings eval
  eval(IO.read(config_file_path), binding)
end

#parse_templates_at_startupObject

:nodoc:



1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
# File 'lib/masterview/initializer.rb', line 1145

def parse_templates_at_startup #:nodoc:
  if configuration.parse_masterview_templates_at_startup
    require 'masterview/extras/watcher'
    MasterView::Log.debug { 'Parsing MasterView templates...' }
    MasterView::IOMgr.template.find(:pattern => MasterView::TemplateFilenamePattern) do |mio|
      MasterView::Parser.parse_mio(mio, MasterView::IOMgr.erb)
    end
    MasterView::LoadedFeatures[:rails_parse_at_startup] = true
  end
end

#processObject

Load the MasterView configuration settings and initialize the template engine.



887
888
889
890
891
# File 'lib/masterview/initializer.rb', line 887

def process
  initialize_configuration
  load_plugin
  complete_plugin_installation
end

#set_module_constantsObject

:nodoc:



987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
# File 'lib/masterview/initializer.rb', line 987

def set_module_constants #:nodoc:

  config = configuration

  # create loaded feature map - this map will track exactly what was loaded taking into account failures, so it can differ
  # from what is configured. key = feature symbol, value = true if enabled and loaded
  MasterView.const_set('LoadedFeatures', {} )

  # we don't record root_path or config_dir_path - their purpose is satisfied
  # by the time we're done processing this installation configuration

  # template source options
  MasterView.const_set('TemplateFilenamePattern', config.template_filename_pattern)

  # template generation options
  MasterView.const_set('OutputExtension', config.output_filename_extension)  ###??IS THIS NEEDED???
  MasterView.const_set('OmitGeneratedComments', (not config.include_generated_file_comment))
  MasterView.const_set('GeneratedCommentText', config.generated_file_comment)

  # template parsing options
  MasterView.const_set('RescueExceptions', config.handle_parse_exceptions)
  MasterView.const_set('DefaultParserOptions', Configuration::OriginalDefaultParserOptions.merge(config.default_parser_options)) # merge in changes with original, so we can add more defaults later, users have to explicitly set an option to false to cancel them
  MasterView.const_set('TidyPath', config.tidy_path)
  MasterView.const_set('InlineErbStart', config.inline_erb_start)
  MasterView.const_set('InlineErbEnd', config.inline_erb_end)
  MasterView.const_set('InlineErbSubstitutionRegex', config.inline_erb_substitution_regex)
  MasterView.const_set('UseOriginalRexmlSax2Parser', config.use_original_rexml_sax2parser)

  # Rails application options
  MasterView.const_set('ParseMasterViewTemplatesAtStartup', config.parse_masterview_templates_at_startup)
  MasterView.const_set('ReparseChangedMasterViewTemplates', config.reparse_changed_masterview_templates)
  MasterView.const_set('EnableMasterViewAdminPages', config.enable_admin_pages)
  MasterView.const_set('EnableMasterViewAdminViewRHTML', config.enable_view_rhtml)

end

#set_rexml_parser_classObject

set the REXML SAX2ParserClass, use patched parser or standard SAX2Parser checks version of REXML and value of :use_patched_rexml_sax2parser



1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
# File 'lib/masterview/initializer.rb', line 1105

def set_rexml_parser_class
  if REXML::Version < '3.1.4' # below minimum version
    MasterView::Log.error { 'Fatal error: MasterView requires REXML version 3.1.4 or greater' }
    raise 'Fatal error: MasterView requires REXML version 3.1.4 or greater'
  elsif MasterView::UseOriginalRexmlSax2Parser || !['3.1.4', '3.1.5', '3.1.6'].include?(REXML::Version)
    MasterView::Log.info { 'MasterView using REXML Sax2Parser version = '+REXML::Version }
    require 'rexml/parsers/sax2parser'
    MasterView.const_set('REXMLSax2ParserClass', REXML::Parsers::SAX2Parser)
  else
    MasterView::Log.info { 'MasterView using REXML '+REXML::VERSION+' Sax2ParserWithDoctypeFix' }
    require 'rexml/parsers/sax2parser_with_doctype_fix'
    MasterView.const_set('REXMLSax2ParserClass', REXML::Parsers::SAX2ParserWithDoctypeFix)
  end
end