pager-engines 2.0.20080513
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +267 -0
- data/MIT-LICENSE +21 -0
- data/README +83 -0
- data/Rakefile +188 -0
- data/about.yml +7 -0
- data/boot.rb +19 -0
- data/generators/plugin_migration/USAGE +45 -0
- data/generators/plugin_migration/plugin_migration_generator.rb +79 -0
- data/generators/plugin_migration/templates/plugin_migration.erb +13 -0
- data/init.rb +5 -0
- data/lib/engines.rb +174 -0
- data/lib/engines/assets.rb +38 -0
- data/lib/engines/plugin.rb +142 -0
- data/lib/engines/plugin/list.rb +30 -0
- data/lib/engines/plugin/loader.rb +18 -0
- data/lib/engines/plugin/locator.rb +37 -0
- data/lib/engines/plugin/migrator.rb +73 -0
- data/lib/engines/rails_extensions/action_mailer.rb +85 -0
- data/lib/engines/rails_extensions/asset_helpers.rb +119 -0
- data/lib/engines/rails_extensions/dependencies.rb +145 -0
- data/lib/engines/rails_extensions/migrations.rb +161 -0
- data/lib/engines/rails_extensions/rails.rb +11 -0
- data/lib/engines/rails_extensions/routing.rb +84 -0
- data/lib/engines/testing.rb +87 -0
- data/lib/engines_initializer.rb +5 -0
- data/rails/init.rb +5 -0
- data/tasks/engines.rake +179 -0
- data/test/app/controllers/app_and_plugin_controller.rb +5 -0
- data/test/app/controllers/application.rb +18 -0
- data/test/app/controllers/namespace/app_and_plugin_controller.rb +5 -0
- data/test/app/helpers/mail_helper.rb +5 -0
- data/test/app/models/app_and_plugin_model.rb +3 -0
- data/test/app/models/notify_mail.rb +26 -0
- data/test/app/things/thing.rb +3 -0
- data/test/app/views/app_and_plugin/a_view.html.erb +1 -0
- data/test/app/views/namespace/app_and_plugin/a_view.html.erb +1 -0
- data/test/app/views/notify_mail/implicit_multipart.text.html.erb +1 -0
- data/test/app/views/notify_mail/implicit_multipart.text.plain.erb +1 -0
- data/test/app/views/notify_mail/multipart_html.html.erb +1 -0
- data/test/app/views/notify_mail/multipart_plain.html.erb +1 -0
- data/test/app/views/notify_mail/signup.text.plain.erb +5 -0
- data/test/app/views/plugin_mail/mail_from_plugin_with_application_template.text.plain.erb +1 -0
- data/test/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb +1 -0
- data/test/functional/controller_loading_test.rb +51 -0
- data/test/functional/routes_test.rb +33 -0
- data/test/functional/view_helpers_test.rb +32 -0
- data/test/functional/view_loading_test.rb +60 -0
- data/test/lib/app_and_plugin_lib_model.rb +3 -0
- data/test/lib/engines_test_helper.rb +36 -0
- data/test/plugins/alpha_plugin/app/controllers/alpha_plugin_controller.rb +8 -0
- data/test/plugins/alpha_plugin/app/controllers/app_and_plugin_controller.rb +5 -0
- data/test/plugins/alpha_plugin/app/controllers/namespace/alpha_plugin_controller.rb +5 -0
- data/test/plugins/alpha_plugin/app/controllers/namespace/app_and_plugin_controller.rb +5 -0
- data/test/plugins/alpha_plugin/app/controllers/namespace/shared_plugin_controller.rb +5 -0
- data/test/plugins/alpha_plugin/app/controllers/shared_plugin_controller.rb +5 -0
- data/test/plugins/alpha_plugin/app/models/alpha_plugin_model.rb +3 -0
- data/test/plugins/alpha_plugin/app/models/app_and_plugin_model.rb +7 -0
- data/test/plugins/alpha_plugin/app/models/shared_plugin_model.rb +3 -0
- data/test/plugins/alpha_plugin/app/views/alpha_plugin/a_view.html.erb +1 -0
- data/test/plugins/alpha_plugin/app/views/app_and_plugin/a_view.html.erb +1 -0
- data/test/plugins/alpha_plugin/app/views/layouts/plugin_layout.erb +1 -0
- data/test/plugins/alpha_plugin/app/views/namespace/alpha_plugin/a_view.html.erb +1 -0
- data/test/plugins/alpha_plugin/app/views/namespace/app_and_plugin/a_view.html.erb +1 -0
- data/test/plugins/alpha_plugin/app/views/namespace/shared_plugin/a_view.html.erb +1 -0
- data/test/plugins/alpha_plugin/app/views/shared_plugin/a_view.html.erb +1 -0
- data/test/plugins/alpha_plugin/lib/alpha_plugin_lib_model.rb +3 -0
- data/test/plugins/alpha_plugin/lib/app_and_plugin_lib_model.rb +7 -0
- data/test/plugins/beta_plugin/app/controllers/app_and_plugin_controller.rb +5 -0
- data/test/plugins/beta_plugin/app/controllers/namespace/shared_plugin_controller.rb +5 -0
- data/test/plugins/beta_plugin/app/controllers/shared_plugin_controller.rb +5 -0
- data/test/plugins/beta_plugin/app/models/shared_plugin_model.rb +3 -0
- data/test/plugins/beta_plugin/app/views/namespace/shared_plugin/a_view.html.erb +1 -0
- data/test/plugins/beta_plugin/app/views/shared_plugin/a_view.html.erb +1 -0
- data/test/plugins/beta_plugin/init.rb +1 -0
- data/test/plugins/not_a_plugin/public/should_not_be_copied.txt +0 -0
- data/test/plugins/test_assets/app/controllers/assets_controller.rb +2 -0
- data/test/plugins/test_assets/app/views/assets/index.html.erb +3 -0
- data/test/plugins/test_assets/app/views/layouts/assets.html.erb +3 -0
- data/test/plugins/test_assets/init.rb +0 -0
- data/test/plugins/test_assets/public/file.txt +0 -0
- data/test/plugins/test_assets/public/subfolder/file_in_subfolder.txt +0 -0
- data/test/plugins/test_assets_with_assets_directory/assets/file.txt +0 -0
- data/test/plugins/test_assets_with_assets_directory/assets/subfolder/file_in_subfolder.txt +0 -0
- data/test/plugins/test_assets_with_assets_directory/init.rb +0 -0
- data/test/plugins/test_assets_with_no_subdirectory/assets/file.txt +0 -0
- data/test/plugins/test_assets_with_no_subdirectory/init.rb +0 -0
- data/test/plugins/test_code_mixing/app/things/thing.rb +3 -0
- data/test/plugins/test_code_mixing/init.rb +1 -0
- data/test/plugins/test_load_path/init.rb +0 -0
- data/test/plugins/test_migration/db/migrate/001_create_tests.rb +11 -0
- data/test/plugins/test_migration/db/migrate/002_create_others.rb +11 -0
- data/test/plugins/test_migration/init.rb +0 -0
- data/test/plugins/test_plugin_mailing/app/models/plugin_mail.rb +26 -0
- data/test/plugins/test_plugin_mailing/app/views/plugin_mail/mail_from_plugin.text.plain.erb +1 -0
- data/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_html.html.erb +1 -0
- data/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_plain.html.erb +1 -0
- data/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_html.html.erb +1 -0
- data/test/plugins/test_plugin_mailing/app/views/plugin_mail/multipart_from_plugin_with_application_template_plain.html.erb +1 -0
- data/test/plugins/test_plugin_mailing/init.rb +0 -0
- data/test/plugins/test_routing/app/controllers/namespace/test_routing_controller.rb +5 -0
- data/test/plugins/test_routing/app/controllers/test_routing_controller.rb +9 -0
- data/test/plugins/test_routing/init.rb +0 -0
- data/test/plugins/test_routing/routes.rb +2 -0
- data/test/plugins/test_testing/init.rb +0 -0
- data/test/plugins/test_testing/test/fixtures/testing_fixtures.yml +0 -0
- data/test/unit/action_mailer_test.rb +54 -0
- data/test/unit/arbitrary_code_mixing_test.rb +41 -0
- data/test/unit/assets_test.rb +48 -0
- data/test/unit/backwards_compat_test.rb +8 -0
- data/test/unit/load_path_test.rb +58 -0
- data/test/unit/migration_test.rb +43 -0
- data/test/unit/model_and_lib_test.rb +37 -0
- data/test/unit/plugins_test.rb +11 -0
- data/test/unit/testing_test.rb +18 -0
- metadata +255 -0
data/about.yml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
author: James Adam
|
|
2
|
+
email: james.adam@gmail.com
|
|
3
|
+
homepage: http://www.rails-engines.org
|
|
4
|
+
summary: Enhances the plugin mechanism to perform more flexible sharing
|
|
5
|
+
description: The Rails Engines plugin allows the sharing of almost any type of code or asset that you could use in a Rails application, including controllers, models, stylesheets, and views.
|
|
6
|
+
license: MIT
|
|
7
|
+
version: 2.0.0-RC1
|
data/boot.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'rails/version'
|
|
3
|
+
unless Rails::VERSION::MAJOR >= 2 ||
|
|
4
|
+
(Rails::VERSION::MAJOR >= 1 && Rails::VERSION::MINOR >= 99)
|
|
5
|
+
raise "This version of the engines plugin requires Rails 2.0 or later!"
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), 'lib/engines')
|
|
10
|
+
|
|
11
|
+
# initialize Rails::Configuration with our own default values to spare users
|
|
12
|
+
# some hassle with the installation and keep the environment cleaner
|
|
13
|
+
|
|
14
|
+
{ :default_plugin_locators => [Engines::Plugin::FileSystemLocator,
|
|
15
|
+
(Engines::Plugin::GemLocator if defined?(Gem))].compact ,
|
|
16
|
+
:default_plugin_loader => Engines::Plugin::Loader,
|
|
17
|
+
:default_plugins => [:engines, :all] }.each do |name, default|
|
|
18
|
+
Rails::Configuration.send(:define_method, name) { default }
|
|
19
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
The plugin migration generator assists in working with schema additions
|
|
3
|
+
required by plugins. Instead of running migrations from plugins directly,
|
|
4
|
+
the generator creates a regular Rails migration which will be responsible
|
|
5
|
+
for migrating the plugins from their current version to the latest version
|
|
6
|
+
installed.
|
|
7
|
+
|
|
8
|
+
This is important because the set of application migrations remains an
|
|
9
|
+
accurate record of the state of the database, even as plugins are installed
|
|
10
|
+
and removed during the development process.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
./script/generate plugin_migration [<plugin_name> <another_plugin_name> ...]
|
|
14
|
+
|
|
15
|
+
This will generate:
|
|
16
|
+
|
|
17
|
+
RAILS_ROOT
|
|
18
|
+
|- db
|
|
19
|
+
|-migrate
|
|
20
|
+
|- xxx_plugin_migrations.rb
|
|
21
|
+
|
|
22
|
+
which contains the migrations for the given plugin(s).
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
Advanced Usage:
|
|
26
|
+
|
|
27
|
+
There may be situations where you need *complete* control over the migrations
|
|
28
|
+
of plugins in your application, migrating a certainly plugin down to X, and
|
|
29
|
+
another plugin up to Y, where neither X or Y are the latest migrations for those
|
|
30
|
+
plugins.
|
|
31
|
+
|
|
32
|
+
For those unfortunate few, I have two pieces of advice:
|
|
33
|
+
|
|
34
|
+
1. Why? This is a code smell [http://c2.com/xp/CodeSmell.html].
|
|
35
|
+
|
|
36
|
+
2. Well, OK. Don't panic. You can completely control plugin migrations by
|
|
37
|
+
creating your own migrations. To manually migrate a plugin to a specific
|
|
38
|
+
version, simply use
|
|
39
|
+
|
|
40
|
+
Engines.plugins[:your_plugin_name].migrate(version)
|
|
41
|
+
|
|
42
|
+
where version is the integer of the migration this plugin should end
|
|
43
|
+
up at.
|
|
44
|
+
|
|
45
|
+
With great power comes great responsibility. Use this wisely.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Generates a migration which migrates all plugins to their latest versions
|
|
2
|
+
# within the database.
|
|
3
|
+
class PluginMigrationGenerator < Rails::Generator::Base
|
|
4
|
+
|
|
5
|
+
def initialize(runtime_args, runtime_options={})
|
|
6
|
+
super
|
|
7
|
+
@options = {:assigns => {}}
|
|
8
|
+
|
|
9
|
+
ensure_plugin_schema_table_exists
|
|
10
|
+
get_plugins_to_migrate(runtime_args)
|
|
11
|
+
|
|
12
|
+
if @plugins_to_migrate.empty?
|
|
13
|
+
puts "All plugins are migrated to their latest versions"
|
|
14
|
+
exit(0)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@options[:migration_file_name] = build_migration_name
|
|
18
|
+
@options[:assigns][:class_name] = build_migration_name.classify
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def manifest
|
|
22
|
+
record do |m|
|
|
23
|
+
m.migration_template 'plugin_migration.erb', 'db/migrate', @options
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
# Create the plugin schema table if it doesn't already exist. See
|
|
30
|
+
# Engines::RailsExtensions::Migrations#initialize_schema_migrations_table_with_engine_additions
|
|
31
|
+
def ensure_plugin_schema_table_exists
|
|
32
|
+
ActiveRecord::Base.connection.initialize_schema_migrations_table
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Determine all the plugins which have migrations that aren't present
|
|
36
|
+
# according to the plugin schema information from the database.
|
|
37
|
+
def get_plugins_to_migrate(plugin_names)
|
|
38
|
+
|
|
39
|
+
# First, grab all the plugins which exist and have migrations
|
|
40
|
+
@plugins_to_migrate = if plugin_names.empty?
|
|
41
|
+
Engines.plugins
|
|
42
|
+
else
|
|
43
|
+
plugin_names.map do |name|
|
|
44
|
+
Engines.plugins[name] ? Engines.plugins[name] : raise("Cannot find the plugin '#{name}'")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
@plugins_to_migrate.reject! { |p| p.latest_migration.nil? }
|
|
49
|
+
|
|
50
|
+
# Then find the current versions from the database
|
|
51
|
+
@current_versions = {}
|
|
52
|
+
@plugins_to_migrate.each do |plugin|
|
|
53
|
+
@current_versions[plugin.name] = Engines::Plugin::Migrator.current_version(plugin)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Then find the latest versions from their migration directories
|
|
57
|
+
@new_versions = {}
|
|
58
|
+
@plugins_to_migrate.each do |plugin|
|
|
59
|
+
@new_versions[plugin.name] = plugin.latest_migration
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Remove any plugins that don't need migration
|
|
63
|
+
@plugins_to_migrate.map { |p| p.name }.each do |name|
|
|
64
|
+
@plugins_to_migrate.delete(Engines.plugins[name]) if @current_versions[name] == @new_versions[name]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
@options[:assigns][:plugins] = @plugins_to_migrate
|
|
68
|
+
@options[:assigns][:new_versions] = @new_versions
|
|
69
|
+
@options[:assigns][:current_versions] = @current_versions
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Construct a unique migration name based on the plugins involved and the
|
|
73
|
+
# versions they should reach after this migration is run.
|
|
74
|
+
def build_migration_name
|
|
75
|
+
@plugins_to_migrate.map do |plugin|
|
|
76
|
+
"#{plugin.name}_to_version_#{@new_versions[plugin.name]}"
|
|
77
|
+
end.join("_and_")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class <%= class_name %> < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
<%- plugins.each do |plugin| -%>
|
|
4
|
+
Engines.plugins["<%= plugin.name %>"].migrate(<%= new_versions[plugin.name] %>)
|
|
5
|
+
<%- end -%>
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.down
|
|
9
|
+
<%- plugins.each do |plugin| -%>
|
|
10
|
+
Engines.plugins["<%= plugin.name %>"].migrate(<%= current_versions[plugin.name] %>)
|
|
11
|
+
<%- end -%>
|
|
12
|
+
end
|
|
13
|
+
end
|
data/init.rb
ADDED
data/lib/engines.rb
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'engines/plugin')
|
|
3
|
+
require File.join(File.dirname(__FILE__), 'engines/plugin/list')
|
|
4
|
+
require File.join(File.dirname(__FILE__), 'engines/plugin/loader')
|
|
5
|
+
require File.join(File.dirname(__FILE__), 'engines/plugin/locator')
|
|
6
|
+
require File.join(File.dirname(__FILE__), 'engines/assets')
|
|
7
|
+
require File.join(File.dirname(__FILE__), 'engines/rails_extensions/rails')
|
|
8
|
+
|
|
9
|
+
# == Parameters
|
|
10
|
+
#
|
|
11
|
+
# The Engines module has a number of public configuration parameters:
|
|
12
|
+
#
|
|
13
|
+
# [+public_directory+] The directory into which plugin assets should be
|
|
14
|
+
# mirrored. Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
|
|
15
|
+
# [+schema_info_table+] The table to use when storing plugin migration
|
|
16
|
+
# version information. Defaults to +plugin_schema_info+.
|
|
17
|
+
#
|
|
18
|
+
# Additionally, there are a few flags which control the behaviour of
|
|
19
|
+
# some of the features the engines plugin adds to Rails:
|
|
20
|
+
#
|
|
21
|
+
# [+disable_application_view_loading+] A boolean flag determining whether
|
|
22
|
+
# or not views should be loaded from
|
|
23
|
+
# the main <tt>app/views</tt> directory.
|
|
24
|
+
# Defaults to false; probably only
|
|
25
|
+
# useful when testing your plugin.
|
|
26
|
+
# [+disable_application_code_loading+] A boolean flag determining whether
|
|
27
|
+
# or not to load controllers/helpers
|
|
28
|
+
# from the main +app+ directory,
|
|
29
|
+
# if corresponding code exists within
|
|
30
|
+
# a plugin. Defaults to false; again,
|
|
31
|
+
# probably only useful when testing
|
|
32
|
+
# your plugin.
|
|
33
|
+
# [+disable_code_mixing+] A boolean flag indicating whether all plugin
|
|
34
|
+
# copies of a particular controller/helper should
|
|
35
|
+
# be loaded and allowed to override each other,
|
|
36
|
+
# or if the first matching file should be loaded
|
|
37
|
+
# instead. Defaults to false.
|
|
38
|
+
#
|
|
39
|
+
module Engines
|
|
40
|
+
# The set of all loaded plugins
|
|
41
|
+
mattr_accessor :plugins
|
|
42
|
+
self.plugins = Engines::Plugin::List.new
|
|
43
|
+
|
|
44
|
+
# List of extensions to load, can be changed in init.rb before calling Engines.init
|
|
45
|
+
mattr_accessor :rails_extensions
|
|
46
|
+
self.rails_extensions = %w(action_mailer asset_helpers routing migrations dependencies)
|
|
47
|
+
|
|
48
|
+
# The name of the public directory to mirror public engine assets into.
|
|
49
|
+
# Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
|
|
50
|
+
mattr_accessor :public_directory
|
|
51
|
+
self.public_directory = File.join(RAILS_ROOT, 'public', 'plugin_assets')
|
|
52
|
+
|
|
53
|
+
# The table in which to store plugin schema information. Defaults to
|
|
54
|
+
# "plugin_schema_info".
|
|
55
|
+
mattr_accessor :schema_info_table
|
|
56
|
+
self.schema_info_table = "plugin_schema_info"
|
|
57
|
+
|
|
58
|
+
#--
|
|
59
|
+
# These attributes control the behaviour of the engines extensions
|
|
60
|
+
#++
|
|
61
|
+
|
|
62
|
+
# Set this to true if views should *only* be loaded from plugins
|
|
63
|
+
mattr_accessor :disable_application_view_loading
|
|
64
|
+
self.disable_application_view_loading = false
|
|
65
|
+
|
|
66
|
+
# Set this to true if controller/helper code shouldn't be loaded
|
|
67
|
+
# from the application
|
|
68
|
+
mattr_accessor :disable_application_code_loading
|
|
69
|
+
self.disable_application_code_loading = false
|
|
70
|
+
|
|
71
|
+
# Set this ti true if code should not be mixed (i.e. it will be loaded
|
|
72
|
+
# from the first valid path on $LOAD_PATH)
|
|
73
|
+
mattr_accessor :disable_code_mixing
|
|
74
|
+
self.disable_code_mixing = false
|
|
75
|
+
|
|
76
|
+
# This is used to determine which files are candidates for the "code
|
|
77
|
+
# mixing" feature that the engines plugin provides, where classes from
|
|
78
|
+
# plugins can be loaded, and then code from the application loaded
|
|
79
|
+
# on top of that code to override certain methods.
|
|
80
|
+
mattr_accessor :code_mixing_file_types
|
|
81
|
+
self.code_mixing_file_types = %w(controller helper)
|
|
82
|
+
|
|
83
|
+
class << self
|
|
84
|
+
def init
|
|
85
|
+
load_extensions
|
|
86
|
+
Engines::Assets.initialize_base_public_directory
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def logger
|
|
90
|
+
RAILS_DEFAULT_LOGGER
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def load_extensions
|
|
94
|
+
rails_extensions.each { |name| require "engines/rails_extensions/#{name}" }
|
|
95
|
+
# load the testing extensions, if we are in the test environment.
|
|
96
|
+
require "engines/testing" if RAILS_ENV == "test"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def select_existing_paths(paths)
|
|
100
|
+
paths.select { |path| File.directory?(path) }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# The engines plugin will, by default, mix code from controllers and helpers,
|
|
104
|
+
# allowing application code to override specific methods in the corresponding
|
|
105
|
+
# controller or helper classes and modules. However, if other file types should
|
|
106
|
+
# also be mixed like this, they can be added by calling this method. For example,
|
|
107
|
+
# if you want to include "things" within your plugin and override them from
|
|
108
|
+
# your applications, you should use the following layout:
|
|
109
|
+
#
|
|
110
|
+
# app/
|
|
111
|
+
# +-- things/
|
|
112
|
+
# | +-- one_thing.rb
|
|
113
|
+
# | +-- another_thing.rb
|
|
114
|
+
# ...
|
|
115
|
+
# vendor/
|
|
116
|
+
# +-- plugins/
|
|
117
|
+
# +-- my_plugin/
|
|
118
|
+
# +-- app/
|
|
119
|
+
# +-- things/
|
|
120
|
+
# +-- one_thing.rb
|
|
121
|
+
# +-- another_thing.rb
|
|
122
|
+
#
|
|
123
|
+
# The important point here is that your "things" are named <whatever>_thing.rb,
|
|
124
|
+
# and that they are placed within plugin/app/things (the pluralized form of 'thing').
|
|
125
|
+
#
|
|
126
|
+
# It's important to note that you'll also want to ensure that the "things" are
|
|
127
|
+
# on your load path in your plugin's init.rb:
|
|
128
|
+
#
|
|
129
|
+
# Rails.plugins[:my_plugin].code_paths << "app/things"
|
|
130
|
+
#
|
|
131
|
+
def mix_code_from(*types)
|
|
132
|
+
self.code_mixing_file_types += types.map { |x| x.to_s.singularize }
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# A general purpose method to mirror a directory (+source+) into a destination
|
|
136
|
+
# directory, including all files and subdirectories. Files will not be mirrored
|
|
137
|
+
# if they are identical already (checked via FileUtils#identical?).
|
|
138
|
+
def mirror_files_from(source, destination)
|
|
139
|
+
return unless File.directory?(source)
|
|
140
|
+
|
|
141
|
+
# TODO: use Rake::FileList#pathmap?
|
|
142
|
+
source_files = Dir[source + "/**/*"]
|
|
143
|
+
source_dirs = source_files.select { |d| File.directory?(d) }
|
|
144
|
+
source_files -= source_dirs
|
|
145
|
+
|
|
146
|
+
unless source_files.empty?
|
|
147
|
+
base_target_dir = File.join(destination, File.dirname(source_files.first))
|
|
148
|
+
FileUtils.mkdir_p(base_target_dir)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
source_dirs.each do |dir|
|
|
152
|
+
# strip down these paths so we have simple, relative paths we can
|
|
153
|
+
# add to the destination
|
|
154
|
+
target_dir = File.join(destination, dir.gsub(source, ''))
|
|
155
|
+
begin
|
|
156
|
+
FileUtils.mkdir_p(target_dir)
|
|
157
|
+
rescue Exception => e
|
|
158
|
+
raise "Could not create directory #{target_dir}: \n" + e
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
source_files.each do |file|
|
|
163
|
+
begin
|
|
164
|
+
target = File.join(destination, file.gsub(source, ''))
|
|
165
|
+
unless File.exist?(target) && FileUtils.identical?(file, target)
|
|
166
|
+
FileUtils.cp(file, target)
|
|
167
|
+
end
|
|
168
|
+
rescue Exception => e
|
|
169
|
+
raise "Could not copy #{file} to #{target}: \n" + e
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Engines
|
|
2
|
+
module Assets
|
|
3
|
+
class << self
|
|
4
|
+
@@readme = %{Files in this directory are automatically generated from your plugins.
|
|
5
|
+
They are copied from the 'assets' directories of each plugin into this directory
|
|
6
|
+
each time Rails starts (script/server, script/console... and so on).
|
|
7
|
+
Any edits you make will NOT persist across the next server restart; instead you
|
|
8
|
+
should edit the files within the <plugin_name>/assets/ directory itself.}
|
|
9
|
+
|
|
10
|
+
# Ensure that the plugin asset subdirectory of RAILS_ROOT/public exists, and
|
|
11
|
+
# that we've added a little warning message to instruct developers not to mess with
|
|
12
|
+
# the files inside, since they're automatically generated.
|
|
13
|
+
def initialize_base_public_directory
|
|
14
|
+
dir = Engines.public_directory
|
|
15
|
+
unless File.exist?(dir)
|
|
16
|
+
Engines.logger.debug "Creating public engine files directory '#{dir}'"
|
|
17
|
+
FileUtils.mkdir_p(dir)
|
|
18
|
+
end
|
|
19
|
+
readme = File.join(dir, "README")
|
|
20
|
+
File.open(readme, 'w') { |f| f.puts @@readme } unless File.exist?(readme)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Replicates the subdirectories under the plugins's +assets+ (or +public+)
|
|
24
|
+
# directory into the corresponding public directory. See also
|
|
25
|
+
# Plugin#public_directory for more.
|
|
26
|
+
def mirror_files_for(plugin)
|
|
27
|
+
return if plugin.public_directory.nil?
|
|
28
|
+
begin
|
|
29
|
+
Engines.logger.debug "Attempting to copy plugin assets from '#{plugin.public_directory}' to '#{Engines.public_directory}'"
|
|
30
|
+
Engines.mirror_files_from(plugin.public_directory, File.join(Engines.public_directory, plugin.name))
|
|
31
|
+
rescue Exception => e
|
|
32
|
+
Engines.logger.warn "WARNING: Couldn't create the public file structure for plugin '#{plugin.name}'; Error follows:"
|
|
33
|
+
Engines.logger.warn e
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# An instance of Plugin is created for each plugin loaded by Rails, and
|
|
2
|
+
# stored in the <tt>Engines.plugins</tt> PluginList
|
|
3
|
+
# (see Engines::RailsExtensions::RailsInitializer for more details).
|
|
4
|
+
#
|
|
5
|
+
# Engines.plugins[:plugin_name]
|
|
6
|
+
#
|
|
7
|
+
# If this plugin contains paths in directories other than <tt>app/controllers</tt>,
|
|
8
|
+
# <tt>app/helpers</tt>, <tt>app/models</tt> and <tt>components</tt>, authors can
|
|
9
|
+
# declare this by adding extra paths to #code_paths:
|
|
10
|
+
#
|
|
11
|
+
# Rails.plugin[:my_plugin].code_paths << "app/sweepers" << "vendor/my_lib"
|
|
12
|
+
#
|
|
13
|
+
# Other properties of the Plugin instance can also be set.
|
|
14
|
+
module Engines
|
|
15
|
+
module PluginExtension
|
|
16
|
+
def self.included(base)
|
|
17
|
+
# Plugins can add code paths to this attribute in init.rb if they
|
|
18
|
+
# need plugin directories to be added to the load path, i.e.
|
|
19
|
+
#
|
|
20
|
+
# plugin.code_paths << 'app/other_classes'
|
|
21
|
+
#
|
|
22
|
+
# Defaults to ["app/controllers", "app/helpers", "app/models", "components"]
|
|
23
|
+
base.send :attr_accessor, :code_paths
|
|
24
|
+
|
|
25
|
+
# Plugins can add paths to this attribute in init.rb if they need
|
|
26
|
+
# controllers loaded from additional locations.
|
|
27
|
+
base.send :attr_accessor, :controller_paths
|
|
28
|
+
|
|
29
|
+
# The directory in this plugin to mirror into the shared directory
|
|
30
|
+
# under +public+.
|
|
31
|
+
#
|
|
32
|
+
# Defaults to "assets" (see default_public_directory).
|
|
33
|
+
base.send :attr_accessor, :public_directory
|
|
34
|
+
|
|
35
|
+
base.alias_method_chain :initialize, :default_paths
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
protected
|
|
39
|
+
|
|
40
|
+
# The default set of code paths which will be added to $LOAD_PATH
|
|
41
|
+
# and Dependencies.load_paths
|
|
42
|
+
def default_code_paths
|
|
43
|
+
# lib will actually be removed from the load paths when we call
|
|
44
|
+
# uniq! in #inject_into_load_paths, but it's important to keep it
|
|
45
|
+
# around (for the documentation tasks, for instance).
|
|
46
|
+
%w(app/controllers app/helpers app/models components lib)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The default set of code paths which will be added to the routing system
|
|
50
|
+
def default_controller_paths
|
|
51
|
+
%w(app/controllers components)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Attempts to detect the directory to use for public files.
|
|
55
|
+
# If +assets+ exists in the plugin, this will be used. If +assets+ is missing
|
|
56
|
+
# but +public+ is found, +public+ will be used.
|
|
57
|
+
def default_public_directory
|
|
58
|
+
Engines.select_existing_paths(%w(assets public).map { |p| File.join(directory, p) }).first
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def initialize_default_paths
|
|
62
|
+
@code_paths = default_code_paths
|
|
63
|
+
@controller_paths = default_controller_paths
|
|
64
|
+
@public_directory = default_public_directory
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
public
|
|
68
|
+
|
|
69
|
+
def initialize_with_default_paths(*args)
|
|
70
|
+
initialize_without_default_paths(*args)
|
|
71
|
+
initialize_default_paths
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns a list of paths this plugin wishes to make available in $LOAD_PATH
|
|
75
|
+
#
|
|
76
|
+
# Overwrites the correspondend method in the superclass
|
|
77
|
+
def load_paths
|
|
78
|
+
report_nonexistant_or_empty_plugin! unless valid?
|
|
79
|
+
select_existing_paths :code_paths
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Extends the superclass' load method to additionally mirror public assets
|
|
83
|
+
def load(initializer)
|
|
84
|
+
return if loaded?
|
|
85
|
+
super initializer
|
|
86
|
+
add_plugin_view_paths
|
|
87
|
+
Assets.mirror_files_for(self)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# for code_paths and controller_paths select those paths that actually
|
|
91
|
+
# exist in the plugin's directory
|
|
92
|
+
def select_existing_paths(name)
|
|
93
|
+
Engines.select_existing_paths(self.send(name).map { |p| File.join(directory, p) })
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def add_plugin_view_paths
|
|
97
|
+
view_path = File.join(directory, 'app', 'views')
|
|
98
|
+
if File.exist?(view_path)
|
|
99
|
+
ActionController::Base.view_paths.insert(1, view_path) # push it just underneath the app
|
|
100
|
+
ActionView::TemplateFinder.process_view_paths(view_path)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# The path to this plugin's public files
|
|
105
|
+
def public_asset_directory
|
|
106
|
+
"#{File.basename(Engines.public_directory)}/#{name}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# The path to this plugin's routes file
|
|
110
|
+
def routes_path
|
|
111
|
+
File.join(directory, "routes.rb")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# The directory containing this plugin's migrations (<tt>plugin/db/migrate</tt>)
|
|
115
|
+
def migration_directory
|
|
116
|
+
File.join(self.directory, 'db', 'migrate')
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Returns the version number of the latest migration for this plugin. Returns
|
|
120
|
+
# nil if this plugin has no migrations.
|
|
121
|
+
def latest_migration
|
|
122
|
+
migrations = Dir[migration_directory+"/*.rb"]
|
|
123
|
+
return nil if migrations.empty?
|
|
124
|
+
migrations.map { |p| File.basename(p) }.sort.last.match(/0*(\d+)\_/)[1].to_i
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Migrate this plugin to the given version. See Engines::Plugin::Migrator for more
|
|
128
|
+
# information.
|
|
129
|
+
def migrate(version = nil)
|
|
130
|
+
Engines::Plugin::Migrator.migrate_plugin(self, version)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class Plugin < Rails::Plugin
|
|
135
|
+
include PluginExtension
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
class GemPlugin < Rails::GemPlugin
|
|
139
|
+
include PluginExtension
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|