parlement 0.10 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CHANGES +11 -0
  2. data/MEMORY +9 -1
  3. data/README +5 -4
  4. data/app/controllers/account_controller.rb +10 -13
  5. data/app/controllers/application.rb +4 -5
  6. data/app/controllers/elt_controller.rb +9 -7
  7. data/app/controllers/person_controller.rb +1 -3
  8. data/app/controllers/subscriber_controller.rb +10 -10
  9. data/app/helpers/elt_helper.rb +2 -0
  10. data/app/models/elt.rb +28 -19
  11. data/app/models/mail.rb +26 -14
  12. data/app/models/mail_notify.rb +5 -4
  13. data/app/models/person.rb +11 -2
  14. data/app/views/account/_login.rhtml +3 -3
  15. data/app/views/account/_show.rhtml +12 -14
  16. data/app/views/elt/_choice.rhtml +3 -3
  17. data/app/views/elt/_elt.rhtml +4 -4
  18. data/app/views/elt/_list.rhtml +2 -2
  19. data/app/views/elt/_listByDate.rhtml +1 -1
  20. data/app/views/elt/_listByVote.rhtml +1 -1
  21. data/app/views/elt/new.rhtml +3 -3
  22. data/app/views/elt/show.rhtml +2 -2
  23. data/app/views/layouts/top.rhtml +6 -0
  24. data/app/views/mail_notify/publish.text.html.rhtml +1 -1
  25. data/app/views/person/_listElts.rhtml +5 -3
  26. data/app/views/person/show.rhtml +1 -2
  27. data/config/boot.rb +5 -4
  28. data/config/environment.rb +6 -4
  29. data/config/routes.rb +3 -2
  30. data/db/development_structure.sql +15 -4
  31. data/db/migrate/006_last_activity.rb +10 -0
  32. data/db/schema.rb +67 -49
  33. data/public/dispatch.fcgi +1 -0
  34. data/public/javascripts/controls.js +41 -23
  35. data/public/javascripts/dragdrop.js +317 -99
  36. data/public/javascripts/effects.js +301 -166
  37. data/public/javascripts/prototype.js +932 -402
  38. data/public/stylesheets/default.css +3 -2
  39. data/test/unit/elt_test.rb +13 -0
  40. data/test/unit/mail_test.rb +3 -1
  41. data/vendor/plugins/engines/CHANGELOG +203 -99
  42. data/vendor/plugins/engines/MIT-LICENSE +1 -1
  43. data/vendor/plugins/engines/README +32 -384
  44. data/vendor/plugins/engines/Rakefile +14 -0
  45. data/vendor/plugins/engines/UPGRADING +93 -0
  46. data/vendor/plugins/engines/about.yml +7 -0
  47. data/vendor/plugins/engines/generators/plugin_migration/USAGE +45 -0
  48. data/vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb +79 -0
  49. data/vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb +13 -0
  50. data/vendor/plugins/engines/init.rb +34 -47
  51. data/vendor/plugins/engines/install.rb +32 -0
  52. data/vendor/plugins/engines/lib/engines/{ruby_extensions.rb → deprecated_config_support.rb} +135 -113
  53. data/vendor/plugins/engines/lib/engines/plugin.rb +214 -0
  54. data/vendor/plugins/engines/lib/engines/plugin_list.rb +31 -0
  55. data/vendor/plugins/engines/lib/engines/plugin_migrator.rb +60 -0
  56. data/vendor/plugins/engines/lib/engines/rails_extensions/active_record.rb +19 -0
  57. data/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb +143 -0
  58. data/vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb +155 -0
  59. data/vendor/plugins/engines/lib/engines/rails_extensions/public_asset_helpers.rb +116 -0
  60. data/vendor/plugins/engines/lib/engines/rails_extensions/rails.rb +20 -0
  61. data/vendor/plugins/engines/lib/engines/rails_extensions/rails_initializer.rb +86 -0
  62. data/vendor/plugins/engines/lib/engines/rails_extensions/routing.rb +77 -0
  63. data/vendor/plugins/engines/lib/engines/rails_extensions/templates.rb +140 -0
  64. data/vendor/plugins/engines/lib/engines/rails_extensions.rb +6 -0
  65. data/vendor/plugins/engines/lib/engines/testing.rb +88 -0
  66. data/vendor/plugins/engines/lib/engines.rb +281 -425
  67. data/vendor/plugins/engines/tasks/engines.rake +108 -137
  68. metadata +218 -250
  69. data/db/ROOT/perso.txt +0 -214
  70. data/public/images/indicator.gif +0 -0
  71. data/public/images/orange_by_darren_Hester_350o.jpg +0 -0
  72. data/public/images/smile.png +0 -0
  73. data/vendor/plugins/engines/generators/engine/USAGE +0 -26
  74. data/vendor/plugins/engines/generators/engine/engine_generator.rb +0 -199
  75. data/vendor/plugins/engines/generators/engine/templates/README +0 -85
  76. data/vendor/plugins/engines/generators/engine/templates/init_engine.erb +0 -15
  77. data/vendor/plugins/engines/generators/engine/templates/install.erb +0 -4
  78. data/vendor/plugins/engines/generators/engine/templates/lib/engine.erb +0 -6
  79. data/vendor/plugins/engines/generators/engine/templates/licenses/GPL +0 -18
  80. data/vendor/plugins/engines/generators/engine/templates/licenses/LGPL +0 -19
  81. data/vendor/plugins/engines/generators/engine/templates/licenses/MIT +0 -22
  82. data/vendor/plugins/engines/generators/engine/templates/licenses/None +0 -1
  83. data/vendor/plugins/engines/generators/engine/templates/public/javascripts/engine.js +0 -0
  84. data/vendor/plugins/engines/generators/engine/templates/public/stylesheets/engine.css +0 -0
  85. data/vendor/plugins/engines/generators/engine/templates/tasks/engine.rake +0 -0
  86. data/vendor/plugins/engines/generators/engine/templates/test/test_helper.erb +0 -17
  87. data/vendor/plugins/engines/lib/bundles/require_resource.rb +0 -124
  88. data/vendor/plugins/engines/lib/bundles.rb +0 -77
  89. data/vendor/plugins/engines/lib/engines/action_mailer_extensions.rb +0 -140
  90. data/vendor/plugins/engines/lib/engines/action_view_extensions.rb +0 -141
  91. data/vendor/plugins/engines/lib/engines/active_record_extensions.rb +0 -21
  92. data/vendor/plugins/engines/lib/engines/dependencies_extensions.rb +0 -129
  93. data/vendor/plugins/engines/lib/engines/migration_extensions.rb +0 -53
  94. data/vendor/plugins/engines/lib/engines/routing_extensions.rb +0 -28
  95. data/vendor/plugins/engines/lib/engines/testing_extensions.rb +0 -327
  96. data/vendor/plugins/engines/tasks/deprecated_engines.rake +0 -7
  97. data/vendor/plugins/engines/test/action_view_extensions_test.rb +0 -9
  98. data/vendor/plugins/engines/test/ruby_extensions_test.rb +0 -115
  99. data/vendor/plugins/guid/README.TXT +0 -29
  100. data/vendor/plugins/guid/init.rb +0 -30
  101. data/vendor/plugins/guid/lib/usesguid.rb +0 -37
  102. data/vendor/plugins/guid/lib/uuid22.rb +0 -43
  103. data/vendor/plugins/guid/lib/uuidtools.rb +0 -572
  104. data/vendor/plugins/responds_to_parent/MIT-LICENSE +0 -20
  105. data/vendor/plugins/responds_to_parent/README +0 -42
  106. data/vendor/plugins/responds_to_parent/Rakefile +0 -22
  107. data/vendor/plugins/responds_to_parent/init.rb +0 -1
  108. data/vendor/plugins/responds_to_parent/lib/responds_to_parent.rb +0 -46
  109. data/vendor/plugins/responds_to_parent/test/responds_to_parent_test.rb +0 -115
@@ -1,467 +1,323 @@
1
- require 'logger'
1
+ # This file contains the Engines module, which holds most of the logic regarding
2
+ # the startup and management of plugins. See Engines for more details.
3
+ #
4
+ # The engines plugin adds to Rails' existing behaviour by producing the +Rails.plugins+
5
+ # PluginList, a list of all loaded plugins in a form which can be easily queried
6
+ # and manipulated. Each instance of Plugin has methods which are used to enhance
7
+ # their behaviour, including mirroring public assets, add controllers, helpers
8
+ # and views and even migration.
9
+ #
10
+ # = init.rb
11
+ #
12
+ # When the engines plugin loads, it first includes the
13
+ # Engines::RailsExtensions::RailsInitializer module into Rails::Initializer,
14
+ # overriding a number of the methods used to load plugins.
15
+ #
16
+ # Once this is loaded, Engines.init is called to prepare the application
17
+ # and create the relevant new datastructures (including <tt>Rails.plugins</tt>).
18
+ #
19
+ # Finally, each of the extension modules from Engines::RailsExtensionsis
20
+ # loaded and included into the relevant Rails classes and modules, enhancing
21
+ # their behaviour to work better with files from plugins.
2
22
 
3
- # We need to know the version of Rails that we are running before we
4
- # can override any of the dependency stuff, since Rails' own behaviour
5
- # has changed over the various releases. We need to explicily make sure
6
- # that the Rails::VERSION constant is loaded, because such things could
7
- # not automatically be achieved prior to 1.1, and the location of the
8
- # file moved in 1.1.1!
9
- def load_rails_version
10
- # At this point, we can't even rely on RAILS_ROOT existing, so we have to figure
11
- # the path to RAILS_ROOT/vendor/rails manually
12
- rails_base = File.expand_path(
13
- File.join(File.dirname(__FILE__), # RAILS_ROOT/vendor/plugins/engines/lib
14
- '..', # RAILS_ROOT/vendor/plugins/engines
15
- '..', # RAILS_ROOT/vendor/plugins
16
- '..', # RAILS_ROOT/vendor
17
- 'rails', 'railties', 'lib')) # RAILS_ROOT/vendor/rails/railties/lib
18
- begin
19
- load File.join(rails_base, 'rails', 'version.rb')
20
- #puts 'loaded 1.1.1+ from vendor: ' + File.join(rails_base, 'rails', 'version.rb')
21
- rescue MissingSourceFile # this means they DON'T have Rails 1.1.1 or later installed in vendor
22
- begin
23
- load File.join(rails_base, 'rails_version.rb')
24
- #puts 'loaded 1.1.0- from vendor: ' + File.join(rails_base, 'rails_version.rb')
25
- rescue MissingSourceFile # this means they DON'T have Rails 1.1.0 or previous installed in vendor
26
- begin
27
- # try and load version information for Rails 1.1.1 or later from the $LOAD_PATH
28
- require 'rails/version'
29
- #puts 'required 1.1.1+ from load path'
30
- rescue LoadError
31
- # try and load version information for Rails 1.1.0 or previous from the $LOAD_PATH
32
- require 'rails_version'
33
- #puts 'required 1.1.0- from load path'
34
- end
35
- end
36
- end
37
- end
38
-
39
- # Actually perform the load
40
- load_rails_version
41
- #puts "Detected Rails version: #{Rails::VERSION::STRING}"
23
+ require "engines/plugin_list"
24
+ require "engines/plugin"
42
25
 
43
- require 'engines/ruby_extensions'
44
- # ... further files are required at the bottom of this file
26
+ # TODO: define a better logger.
27
+ def logger
28
+ RAILS_DEFAULT_LOGGER
29
+ end
45
30
 
46
- # Holds the Rails Engine loading logic and default constants
31
+ # The Engines module contains most of the methods used during the enhanced
32
+ # startup of Rails plugins.
33
+ #
34
+ # When the Engines plugin loads (its <tt>init.rb</tt> file is evaluated), the
35
+ # Engines.init method is called. This kickstarts the plugins hooks into
36
+ # the initialization process.
37
+ #
38
+ # == Parameters
39
+ #
40
+ # The Engines module has a number of public configuration parameters:
41
+ #
42
+ # [+public_directory+] The directory into which plugin assets should be
43
+ # mirrored. Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
44
+ # [+schema_info_table+] The table to use when storing plugin migration
45
+ # version information. Defaults to +plugin_schema_info+.
46
+ # [+rails_initializer+] A reference of the Rails initializer instance that
47
+ # was used to startup Rails. This is often useful
48
+ # when working with the startup process; see
49
+ # Engines::RailsExtensions::RailsInitializer for more
50
+ # information
51
+ #
52
+ # Additionally, there are a few flags which control the behaviour of
53
+ # some of the features the engines plugin adds to Rails:
54
+ #
55
+ # [+disable_application_view_loading+] A boolean flag determining whether
56
+ # or not views should be loaded from
57
+ # the main <tt>app/views</tt> directory.
58
+ # Defaults to false; probably only
59
+ # useful when testing your plugin.
60
+ # [+disable_application_code_loading+] A boolean flag determining whether
61
+ # or not to load controllers/helpers
62
+ # from the main +app+ directory,
63
+ # if corresponding code exists within
64
+ # a plugin. Defaults to false; again,
65
+ # probably only useful when testing
66
+ # your plugin.
67
+ # [+disable_code_mixing+] A boolean flag indicating whether all plugin
68
+ # copies of a particular controller/helper should
69
+ # be loaded and allowed to override each other,
70
+ # or if the first matching file should be loaded
71
+ # instead. Defaults to false.
72
+ #
47
73
  module Engines
74
+ # The name of the public directory to mirror public engine assets into.
75
+ # Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
76
+ mattr_accessor :public_directory
77
+ self.public_directory = File.join(RAILS_ROOT, 'public', 'plugin_assets')
48
78
 
49
- class << self
50
- # Return the version string for this plugin
51
- def version
52
- "#{Version::Major}.#{Version::Minor}.#{Version::Release}"
53
- end
54
-
55
- # For holding the rails configuration object
56
- attr_accessor :rails_config
57
-
58
- # A flag to stop searching for views in the application
59
- attr_accessor :disable_app_views_loading
60
-
61
- # A flag to stop code being mixed in from the application
62
- attr_accessor :disable_app_code_mixing
63
- end
64
-
65
- # The DummyLogger is a class which might pass through to a real Logger
66
- # if one is assigned. However, it can gracefully swallow any logging calls
67
- # if there is now Logger assigned.
68
- class LoggerWrapper
69
- def initialize(logger=nil)
70
- set_logger(logger)
71
- end
72
- # Assign the 'real' Logger instance that this dummy instance wraps around.
73
- def set_logger(logger)
74
- @logger = logger
75
- end
76
- # log using the appropriate method if we have a logger
77
- # if we dont' have a logger, ignore completely.
78
- def method_missing(name, *args)
79
- if @logger && @logger.respond_to?(name)
80
- @logger.send(name, *args)
81
- end
82
- end
83
- end
84
-
85
- LOGGER = Engines::LoggerWrapper.new
79
+ # The table in which to store plugin schema information. Defaults to
80
+ # "plugin_schema_info".
81
+ mattr_accessor :schema_info_table
82
+ self.schema_info_table = "plugin_schema_info"
86
83
 
87
- class << self
88
- # Create a new Logger instance for Engines, with the given outputter and level
89
- def create_logger(outputter=STDOUT, level=Logger::INFO)
90
- LOGGER.set_logger(Logger.new(outputter, level))
91
- end
92
- # Sets the Logger instance that Engines will use to send logging information to
93
- def set_logger(logger)
94
- Engines::LOGGER.set_logger(logger) # TODO: no need for Engines:: part
95
- end
96
- # Retrieves the current Logger instance
97
- def log
98
- Engines::LOGGER # TODO: no need for Engines:: part
99
- end
100
- alias :logger :log
101
- end
84
+ # A reference to the current Rails::Initializer instance
85
+ mattr_accessor :rails_initializer
102
86
 
103
- # An array of active engines. This should be accessed via the Engines.active method.
104
- ActiveEngines = []
105
87
 
106
- # The root directory for engines
107
- config :root, File.join(RAILS_ROOT, "vendor", "plugins")
88
+ #--
89
+ # These attributes control the behaviour of the engines extensions
90
+ #++
108
91
 
109
- # The name of the public folder under which engine files are copied
110
- config :public_dir, "engine_files"
92
+ # Set this to true if views should *only* be loaded from plugins
93
+ mattr_accessor :disable_application_view_loading
94
+ self.disable_application_view_loading = false
111
95
 
112
- class << self
96
+ # Set this to true if controller/helper code shouldn't be loaded
97
+ # from the application
98
+ mattr_accessor :disable_application_code_loading
99
+ self.disable_application_code_loading = false
113
100
 
114
- # Initializes a Rails Engine by loading the engine's init.rb file and
115
- # ensuring that any engine controllers are added to the load path.
116
- # This will also copy any files in a directory named 'public'
117
- # into the public webserver directory. Example usage:
118
- #
119
- # Engines.start :login
120
- # Engines.start :login_engine # equivalent
121
- #
122
- # A list of engine names can be specified:
123
- #
124
- # Engines.start :login, :user, :wiki
125
- #
126
- # The engines will be loaded in the order given.
127
- # If no engine names are given, all engines will be started.
128
- #
129
- # Options can include:
130
- # * :copy_files => true | false
131
- #
132
- # Note that if a list of engines is given, the options will apply to ALL engines.
133
- def start(*args)
134
-
135
- options = (args.last.is_a? Hash) ? args.pop : {}
136
-
137
- if args.empty?
138
- start_all
139
- else
140
- args.each do |engine_name|
141
- start_engine(engine_name, options)
142
- end
143
- end
144
- end
145
-
146
- # Starts all available engines. Plugins are considered engines if they
147
- # include an init_engine.rb file, or they are named <something>_engine.
148
- def start_all
149
- plugins = Dir[File.join(config(:root), "*")]
150
- Engines.log.debug "considering plugins: #{plugins.inspect}"
151
- plugins.each { |plugin|
152
- engine_name = File.basename(plugin)
153
- if File.exist?(File.join(plugin, "init_engine.rb")) || # if the directory contains init_engine.rb
154
- (engine_name =~ /_engine$/) || # or it engines in '_engines'
155
- (engine_name =~ /_bundle$/) # or even ends in '_bundle'
156
-
157
- start(engine_name) # start the engine...
158
-
159
- end
160
- }
161
- end
162
-
163
- # Initialize the routing controller paths.
164
- def initialize_routing
165
- # See lib/engines/routing_extensions.rb for more information.
166
- ActionController::Routing.controller_paths = Engines.rails_config.controller_paths
167
- end
101
+ # Set this ti true if code should not be mixed (i.e. it will be loaded
102
+ # from the first valid path on $LOAD_PATH)
103
+ mattr_accessor :disable_code_mixing
104
+ self.disable_code_mixing = false
105
+
106
+
107
+ private
168
108
 
169
- def start_engine(engine_name, options={})
170
-
171
- # Create a new Engine and put this engine at the front of the ActiveEngines list
172
- current_engine = Engine.new(engine_name)
173
- Engines.active.unshift current_engine
174
- Engines.log.info "Starting engine '#{current_engine.name}' from '#{File.expand_path(current_engine.root)}'"
109
+ # A memo of the bottom of Rails' default load path
110
+ mattr_accessor :rails_final_load_path
111
+ # A memo of the bottom of Rails Dependencies load path
112
+ mattr_accessor :rails_final_dependency_load_path
113
+
114
+ public
115
+
116
+ # Initializes the engines plugin and prepares Rails to start loading
117
+ # plugins using engines extensions. Within this method:
118
+ #
119
+ # 1. Copies of the Rails configuration and initializer are stored;
120
+ # 2. The Rails.plugins PluginList instance is created;
121
+ # 3. Any plugins which were loaded before the engines plugin are given
122
+ # the engines treatment via #enhance_loaded_plugins.
123
+ # 4. The base public directory (into which plugin assets are mirrored)
124
+ # is created, if necessary - #initialize_base_public_directory
125
+ # 5. <tt>config.plugins</tt> is checked to see if a wildcard was present -
126
+ # #check_for_star_wildcard
127
+ #
128
+ def self.init(rails_configuration, rails_initializer)
129
+ # First, determine if we're running in legacy mode
130
+ @legacy_support = self.const_defined?(:LegacySupport) && LegacySupport
175
131
 
176
- # add the code directories of this engine to the load path
177
- add_engine_to_load_path(current_engine)
132
+ # Store some information about the plugin subsystem
133
+ Rails.configuration = rails_configuration
178
134
 
179
- # add the controller & component path to the Dependency system
180
- engine_controllers = File.join(current_engine.root, 'app', 'controllers')
181
- engine_components = File.join(current_engine.root, 'components')
135
+ # We need a hook into this so we can get freaky with the plugin loading itself
136
+ self.rails_initializer = rails_initializer
137
+
138
+ @load_all_plugins = false
139
+
140
+ store_load_path_markers
141
+
142
+ Rails.plugins ||= PluginList.new
143
+ enhance_loaded_plugins # including this one, as it happens.
182
144
 
145
+ initialize_base_public_directory
146
+
147
+ check_for_star_wildcard
148
+
149
+ logger.debug "engines has started."
150
+ end
183
151
 
184
- # This mechanism is no longer required in Rails trunk
185
- if Rails::VERSION::STRING =~ /^1.0/ && !Engines.config(:edge)
186
- Controllers.add_path(engine_controllers) if File.exist?(engine_controllers)
187
- Controllers.add_path(engine_components) if File.exist?(engine_components)
188
- else
189
- ActionController::Routing.controller_paths << engine_controllers
190
- ActionController::Routing.controller_paths << engine_components
191
- end
192
-
193
- # copy the files unless indicated otherwise
194
- if options[:copy_files] != false
195
- current_engine.mirror_engine_files
196
- end
152
+ # You can enable legacy support by defining the LegacySupport constant
153
+ # in the Engines module before Rails loads, i.e. at the *top* of environment.rb,
154
+ # add:
155
+ #
156
+ # module Engines
157
+ # LegacySupport = true
158
+ # end
159
+ #
160
+ # Legacy Support doesn't actually do anything at the moment. If necessary
161
+ # we may support older-style 'engines' using this flag.
162
+ def self.legacy_support?
163
+ @legacy_support
164
+ end
197
165
 
198
- # load the engine's init.rb file
199
- startup_file = File.join(current_engine.root, "init_engine.rb")
200
- if File.exist?(startup_file)
201
- eval(IO.read(startup_file), binding, startup_file)
202
- # possibly use require_dependency? Hmm.
203
- else
204
- Engines.log.debug "No init_engines.rb file found for engine '#{current_engine.name}'..."
205
- end
206
- end
166
+ # A reference to the currently-loading/loaded plugin. This is present to support
167
+ # legacy engines; it's preferred to use Rails.plugins[name] in your plugin's
168
+ # init.rb file in order to get your Plugin instance.
169
+ def self.current
170
+ Rails.plugins.last
171
+ end
207
172
 
208
- # Adds all directories in the /app and /lib directories within the engine
209
- # to the load path
210
- def add_engine_to_load_path(engine)
211
-
212
- # remove the lib directory added by load_plugin, and place it in the corrent
213
- # location *after* the application/lib. This can be removed when
214
- # http://dev.rubyonrails.org/ticket/2910 is fixed.
215
- app_lib_index = $LOAD_PATH.index(File.join(RAILS_ROOT, "lib"))
216
- engine_lib = File.join(engine.root, "lib")
217
- if app_lib_index
218
- $LOAD_PATH.delete(engine_lib)
219
- $LOAD_PATH.insert(app_lib_index+1, engine_lib)
220
- end
221
-
222
- # Add ALL paths under the engine root to the load path
223
- app_dirs = %w(controllers helpers models).collect { |d|
224
- File.join(engine.root, 'app', d)
225
- }
226
- other_dirs = %w(components lib).collect { |d|
227
- File.join(engine.root, d)
228
- }
229
- load_paths = (app_dirs + other_dirs).select { |d| File.directory?(d) }
173
+ # This is set to true if a "*" widlcard is present at the end of
174
+ # the config.plugins array.
175
+ def self.load_all_plugins?
176
+ @load_all_plugins
177
+ end
230
178
 
231
- # Remove other engines from the $LOAD_PATH by matching against the engine.root values
232
- # in ActiveEngines. Store the removed engines in the order they came off.
233
-
234
- old_plugin_paths = []
235
- # assumes that all engines are at the bottom of the $LOAD_PATH
236
- while (File.expand_path($LOAD_PATH.last).index(File.expand_path(Engines.config(:root))) == 0) do
237
- old_plugin_paths.unshift($LOAD_PATH.pop)
179
+ # Stores a record of the last paths which Rails added to each of the load path
180
+ # attributes ($LOAD_PATH, Dependencies.load_paths and
181
+ # ActionController::Routing.controller_paths) that influence how code is loaded
182
+ # We need this to ensure that we place our additions to the load path *after*
183
+ # all Rails' defaults
184
+ def self.store_load_path_markers
185
+ self.rails_final_load_path = $LOAD_PATH.last
186
+ logger.debug "Rails final load path: #{self.rails_final_load_path}"
187
+ self.rails_final_dependency_load_path = ::Dependencies.load_paths.last
188
+ logger.debug "Rails final dependency load path: #{self.rails_final_dependency_load_path}"
189
+ end
190
+
191
+ # Create Plugin instances for plugins loaded before the engines plugin was.
192
+ # Once a Plugin instance is created, the Plugin#load method is then called
193
+ # to fully load the plugin. See Plugin#load for more details about how a
194
+ # plugin is started once engines is involved.
195
+ def self.enhance_loaded_plugins
196
+ Engines.rails_initializer.loaded_plugins.each do |name|
197
+ plugin_path = File.join(self.find_plugin_path(name), name)
198
+ unless Rails.plugins[name]
199
+ plugin = Plugin.new(name, plugin_path)
200
+ logger.debug "enginizing plugin: #{plugin.name} from #{plugin_path}"
201
+ plugin.load # injects the extra directories into the load path, and mirrors public files
202
+ Rails.plugins << plugin
238
203
  end
239
-
240
-
241
- # add these LAST on the load path.
242
- load_paths.reverse.each { |dir|
243
- if File.directory?(dir)
244
- Engines.log.debug "adding #{File.expand_path(dir)} to the load path"
245
- #$LOAD_PATH.push(File.expand_path(dir))
246
- $LOAD_PATH.push dir
247
- end
248
- }
249
-
250
- # Add the other engines back onto the bottom of the $LOAD_PATH. Put them back on in
251
- # the same order.
252
- $LOAD_PATH.push(*old_plugin_paths)
253
- $LOAD_PATH.uniq!
254
- end
255
-
256
- # Returns the directory in which all engine public assets are mirrored.
257
- def public_engine_dir
258
- File.expand_path(File.join(RAILS_ROOT, "public", Engines.config(:public_dir)))
259
204
  end
205
+ logger.debug "plugins is now: #{Rails.plugins.map { |p| p.name }.join(", ")}"
206
+ end
260
207
 
261
- # create the /public/engine_files directory if it doesn't exist
262
- def create_base_public_directory
263
- if !File.exists?(public_engine_dir)
264
- # create the public/engines directory, with a warning message in it.
265
- Engines.log.debug "Creating public engine files directory '#{public_engine_dir}'"
266
- FileUtils.mkdir(public_engine_dir)
267
- File.open(File.join(public_engine_dir, "README"), "w") do |f|
268
- f.puts <<EOS
269
- Files in this directory are automatically generated from your Rails Engines.
208
+ # Ensure that the plugin asset subdirectory of RAILS_ROOT/public exists, and
209
+ # that we've added a little warning message to instruct developers not to mess with
210
+ # the files inside, since they're automatically generated.
211
+ def self.initialize_base_public_directory
212
+ if !File.exist?(self.public_directory)
213
+ # create the public/engines directory, with a warning message in it.
214
+ logger.debug "Creating public engine files directory '#{self.public_directory}'"
215
+ FileUtils.mkdir(self.public_directory)
216
+ message = %{Files in this directory are automatically generated from your Rails Engines.
270
217
  They are copied from the 'public' directories of each engine into this directory
271
218
  each time Rails starts (server, console... any time 'start_engine' is called).
272
219
  Any edits you make will NOT persist across the next server restart; instead you
273
- should edit the files within the <engine_name>/public/ directory itself.
274
- EOS
275
- end
276
- end
277
- end
278
-
279
- # Returns the Engine object for the specified engine, e.g.:
280
- # Engines.get(:login)
281
- def get(name)
282
- active.find { |e| e.name == name.to_s || e.name == "#{name}_engine" }
283
- end
284
- alias_method :[], :get
285
-
286
- # Returns the Engine object for the current engine, i.e. the engine
287
- # in which the currently executing code lies.
288
- def current
289
- current_file = caller[0]
290
- active.find do |engine|
291
- File.expand_path(current_file).index(File.expand_path(engine.root)) == 0
292
- end
293
- end
294
-
295
- # Returns an array of active engines
296
- def active
297
- ActiveEngines
220
+ should edit the files within the <plugin_name>/assets/ directory itself.}
221
+ target = File.join(public_directory, "README")
222
+ File.open(target, 'w') { |f| f.puts(message) } unless File.exist?(target)
298
223
  end
299
-
300
- # Pass a block to perform an operation on each engine. You may pass an argument
301
- # to determine the order:
302
- #
303
- # * :load_order - in the order they were loaded (i.e. lower precidence engines first).
304
- # * :precidence_order - highest precidence order (i.e. last loaded) first
305
- def each(ordering=:precidence_order, &block)
306
- engines = (ordering == :load_order) ? active.reverse : active
307
- engines.each { |e| yield e }
308
- end
309
- end
310
- end
311
-
312
- # A simple class for holding information about loaded engines
313
- class Engine
314
-
315
- # Returns the base path of this engine
316
- attr_accessor :root
317
-
318
- # Returns the name of this engine
319
- attr_reader :name
320
-
321
- # An attribute for holding the current version of this engine. There are three
322
- # ways of providing an engine version. The simplest is using a string:
323
- #
324
- # Engines.current.version = "1.0.7"
325
- #
326
- # Alternatively you can set it to a module which contains Major, Minor and Release
327
- # constants:
328
- #
329
- # module LoginEngine::Version
330
- # Major = 1; Minor = 0; Release = 6;
331
- # end
332
- # Engines.current.version = LoginEngine::Version
333
- #
334
- # Finally, you can set it to your own Proc, if you need something really fancy:
335
- #
336
- # Engines.current.version = Proc.new { File.open('VERSION', 'r').readlines[0] }
337
- #
338
- attr_writer :version
339
-
340
- # Engine developers can store any information they like in here.
341
- attr_writer :info
224
+ end
342
225
 
343
- # Creates a new object holding information about an Engine.
344
- def initialize(name)
226
+ # Check for a "*" at the end of the plugins list; if one is found, note that
227
+ # we should load all other plugins once Rails has finished initializing, and
228
+ # remove the "*".
229
+ def self.check_for_star_wildcard
230
+ if Rails.configuration.plugins && Rails.configuration.plugins.last == "*"
231
+ Rails.configuration.plugins.pop
232
+ @load_all_plugins = true
233
+ end
234
+ end
345
235
 
346
- @root = ''
347
- suffixes = ['', '_engine', '_bundle']
348
- while !File.exist?(@root) && !suffixes.empty?
349
- suffix = suffixes.shift
350
- @root = File.join(Engines.config(:root), name.to_s + suffix)
351
- end
352
236
 
353
- if !File.exist?(@root)
354
- raise "Cannot find the engine '#{name}' in either /vendor/plugins/#{name}, " +
355
- "/vendor/plugins/#{name}_engine or /vendor/plugins/#{name}_bundle."
356
- end
357
-
358
- @name = File.basename(@root)
359
- end
360
-
361
- # Returns the version string of this engine
362
- def version
363
- case @version
364
- when Module
365
- "#{@version::Major}.#{@version::Minor}.#{@version::Release}"
366
- when Proc # not sure about this
367
- @version.call
368
- when NilClass
369
- 'unknown'
370
- else
371
- @version
237
+ #-
238
+ # The following code is called once all plugins are loaded, and Rails is almost
239
+ # finished initialization
240
+ #+
241
+
242
+ # Once the Rails Initializer has finished, the engines plugin takes over
243
+ # and performs any post-processing tasks it may have, including:
244
+ #
245
+ # * Loading any remaining plugins if config.plugins ended with a '*'.
246
+ # * Updating Rails::Info with version information, if possible.
247
+ #
248
+ def self.after_initialize
249
+ if self.load_all_plugins?
250
+ logger.debug "loading remaining plugins from #{Rails.configuration.plugin_paths.inspect}"
251
+ # this will actually try to load ALL plugins again, but any that have already
252
+ # been loaded will be ignored.
253
+ rails_initializer.load_all_plugins
254
+ update_rails_info_with_loaded_plugins
372
255
  end
373
256
  end
374
257
 
375
- # Returns a string describing this engine
376
- def info
377
- @info || '(none)'
258
+ # Updates Rails::Info with the list of loaded plugins, and version information for
259
+ # each plugin. This information is then available via script/about, or through
260
+ # the builtin rails_info controller.
261
+ def self.update_rails_info_with_loaded_plugins
262
+ if defined?(Rails::Info) # since it may not be available by default in some environments...
263
+ # don't do anything if it's not there.
264
+ Rails::Info.property("Loaded plugins") { Rails.plugins.map { |p| p.name }.join(", ") }
265
+ Rails.plugins.each do |plugin|
266
+ Rails::Info.property("#{plugin.name} version") { plugin.version.blank? ? "(unknown)" : plugin.version }
267
+ end
268
+ end
378
269
  end
379
-
380
- # Returns a string representation of this engine
381
- def to_s
382
- "Engine<'#{@name}' [#{version}]:#{root.gsub(RAILS_ROOT, '')}>"
270
+
271
+ #-
272
+ # helper methods to find and deal with plugin paths and names
273
+ #+
274
+
275
+ # Returns the path within +Rails.configuration.plugin_paths+ which includes
276
+ # a plugin with the given name.
277
+ def self.find_plugin_path(name)
278
+ Rails.configuration.plugin_paths.find do |path|
279
+ File.exist?(File.join(path, name.to_s))
280
+ end
383
281
  end
384
282
 
385
- # return the path to this Engine's public files (with a leading '/' for use in URIs)
386
- def public_dir
387
- File.join("/", Engines.config(:public_dir), name)
283
+ # Returns the name for the plugin at the given path.
284
+ # (Note this method also appears in Rails::Initializer extensions)
285
+ def self.plugin_name(path)
286
+ File.basename(path)
388
287
  end
389
288
 
390
- # Replicates the subdirectories under the engine's /public directory into
391
- # the corresponding public directory.
392
- def mirror_engine_files
289
+ # A general purpose method to mirror a directory (+source+) into a destination
290
+ # directory, including all files and subdirectories. Files will not be mirrored
291
+ # if they are identical already (checked via FileUtils#identical?).
292
+ def self.mirror_files_from(source, destination)
293
+ return unless File.directory?(source)
393
294
 
394
- begin
395
- Engines.create_base_public_directory
396
-
397
- source = File.join(root, "public")
398
- Engines.log.debug "Attempting to copy public engine files from '#{source}'"
399
-
400
- # if there is no public directory, just return after this file
401
- return if !File.exist?(source)
402
-
403
- source_files = Dir[source + "/**/*"]
404
- source_dirs = source_files.select { |d| File.directory?(d) }
405
- source_files -= source_dirs
295
+ # TODO: use Rake::FileList#pathmap?
406
296
 
407
- Engines.log.debug "source dirs: #{source_dirs.inspect}"
408
-
409
- # Create the engine_files/<something>_engine dir if it doesn't exist
410
- new_engine_dir = File.join(RAILS_ROOT, "public", public_dir)
411
- if !File.exists?(new_engine_dir)
412
- # Create <something>_engine dir with a message
413
- Engines.log.debug "Creating #{public_dir} public dir"
414
- FileUtils.mkdir_p(new_engine_dir)
297
+ source_files = Dir[source + "/**/*"]
298
+ source_dirs = source_files.select { |d| File.directory?(d) }
299
+ source_files -= source_dirs
300
+
301
+ source_dirs.each do |dir|
302
+ # strip down these paths so we have simple, relative paths we can
303
+ # add to the destination
304
+ target_dir = File.join(destination, dir.gsub(source, ''))
305
+ begin
306
+ FileUtils.mkdir_p(target_dir)
307
+ rescue Exception => e
308
+ raise "Could not create directory #{target_dir}: \n" + e
415
309
  end
416
-
417
- # create all the directories, transforming the old path into the new path
418
- source_dirs.uniq.each { |dir|
419
- begin
420
- # strip out the base path and add the result to the public path, i.e. replace
421
- # ../script/../vendor/plugins/engine_name/public/javascript
422
- # with
423
- # engine_name/javascript
424
- #
425
- relative_dir = dir.gsub(File.join(root, "public"), name)
426
- target_dir = File.join(Engines.public_engine_dir, relative_dir)
427
- unless File.exist?(target_dir)
428
- Engines.log.debug "creating directory '#{target_dir}'"
429
- FileUtils.mkdir_p(target_dir)
430
- end
431
- rescue Exception => e
432
- raise "Could not create directory #{target_dir}: \n" + e
433
- end
434
- }
435
-
436
- # copy all the files, transforming the old path into the new path
437
- source_files.uniq.each { |file|
438
- begin
439
- # change the path from the ENGINE ROOT to the public directory root for this engine
440
- target = file.gsub(File.join(root, "public"),
441
- File.join(Engines.public_engine_dir, name))
442
- unless File.exist?(target) && FileUtils.identical?(file, target)
443
- Engines.log.debug "copying file '#{file}' to '#{target}'"
444
- FileUtils.cp(file, target)
445
- end
446
- rescue Exception => e
447
- raise "Could not copy #{file} to #{target}: \n" + e
448
- end
449
- }
450
- rescue Exception => e
451
- Engines.log.warn "WARNING: Couldn't create the engine public file structure for engine '#{name}'; Error follows:"
452
- Engines.log.warn e
453
310
  end
454
- end
455
- end
456
-
457
-
458
- # These files must be required after the Engines module has been defined.
459
- require 'engines/dependencies_extensions'
460
- require 'engines/routing_extensions'
461
- require 'engines/action_view_extensions'
462
- require 'engines/action_mailer_extensions'
463
- require 'engines/migration_extensions'
464
- require 'engines/active_record_extensions'
465
311
 
466
- # only load the testing extensions if we are in the test environment
467
- require 'engines/testing_extensions' if %w(test).include?(RAILS_ENV)
312
+ source_files.each do |file|
313
+ begin
314
+ target = File.join(destination, file.gsub(source, ''))
315
+ unless File.exist?(target) && FileUtils.identical?(file, target)
316
+ FileUtils.cp(file, target)
317
+ end
318
+ rescue Exception => e
319
+ raise "Could not copy #{file} to #{target}: \n" + e
320
+ end
321
+ end
322
+ end
323
+ end