ioquatix-engines 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +280 -0
- data/MIT-LICENSE +21 -0
- data/README +95 -0
- data/Rakefile +199 -0
- data/about.yml +7 -0
- data/bin/rails_engines +103 -0
- data/generators/plugin_migration/USAGE +45 -0
- data/generators/plugin_migration/plugin_migration_generator.rb +78 -0
- data/generators/plugin_migration/templates/plugin_migration.erb +13 -0
- data/lib/engines.rb +185 -0
- data/lib/engines/assets.rb +38 -0
- data/lib/engines/load_engine_tasks.rake +6 -0
- data/lib/engines/plugin.rb +173 -0
- data/lib/engines/plugin/list.rb +57 -0
- data/lib/engines/plugin/migrator.rb +45 -0
- data/lib/engines/rails_extensions/action_mailer.rb +85 -0
- data/lib/engines/rails_extensions/asset_helpers.rb +149 -0
- data/lib/engines/rails_extensions/dependencies.rb +151 -0
- data/lib/engines/rails_extensions/routing.rb +88 -0
- data/lib/engines/testing.rb +87 -0
- data/lib/engines/version.rb +10 -0
- data/rails/init.rb +6 -0
- data/tasks/engines.rake +249 -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/exception_notification_compatibility_test.rb +29 -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/db/migrate/003_create_extras.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/load_path_test.rb +58 -0
- data/test/unit/migration_test.rb +63 -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 +259 -0
data/about.yml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
author: Samuel Williams
|
2
|
+
email: samuel.williams@oriontransfer.co.nz
|
3
|
+
homepage: http://wiki.oriontransfer.org/?rails:engines
|
4
|
+
summary: Gemified version of engines plugin. Enhances the plugin mechanism to perform more flexible sharing.
|
5
|
+
description: The Rails Engines plugin was originally created by James Adam and 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.1.0
|
data/bin/rails_engines
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
class Array
|
7
|
+
# Not optimized at all!
|
8
|
+
def matches_sequence? other
|
9
|
+
return true if other.size == 0
|
10
|
+
|
11
|
+
i = index(other.first)
|
12
|
+
|
13
|
+
if i
|
14
|
+
other.each_with_index do |v,p|
|
15
|
+
return false if self[i+p] != v
|
16
|
+
end
|
17
|
+
|
18
|
+
return i
|
19
|
+
else
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def insert_lines(lines_to_insert, options)
|
26
|
+
lines_to_insert = lines_to_insert.collect { |l| l.chomp + "\n" }
|
27
|
+
|
28
|
+
target_file = File.join(options[:into])
|
29
|
+
|
30
|
+
lines = File.readlines(target_file)
|
31
|
+
|
32
|
+
return if lines.matches_sequence?(lines_to_insert)
|
33
|
+
|
34
|
+
if options[:after]
|
35
|
+
if options[:after].is_a?(String)
|
36
|
+
after_line = options[:after] + "\n"
|
37
|
+
else
|
38
|
+
after_line = lines.find { |l| l =~ options[:after] }
|
39
|
+
raise "couldn't find a line matching #{options[:after].inspect} in #{target_file}" unless after_line
|
40
|
+
end
|
41
|
+
index = lines.index(after_line)
|
42
|
+
raise "couldn't find line '#{after_line}' in #{target_file}" unless index
|
43
|
+
lines[index+1,0] = lines_to_insert
|
44
|
+
else
|
45
|
+
lines << line
|
46
|
+
end
|
47
|
+
|
48
|
+
File.open(target_file, 'w') { |f| f.write lines.join }
|
49
|
+
end
|
50
|
+
|
51
|
+
OPTIONS = {
|
52
|
+
:Setup => false
|
53
|
+
}
|
54
|
+
|
55
|
+
ARGV.options do |o|
|
56
|
+
script_name = File.basename($0)
|
57
|
+
|
58
|
+
o.set_summary_indent(' ')
|
59
|
+
o.banner = "Usage: #{script_name} [options]"
|
60
|
+
o.define_head "This script is used to set up the engines plugin for rails."
|
61
|
+
|
62
|
+
o.separator ""
|
63
|
+
o.separator "Help and Copyright information"
|
64
|
+
|
65
|
+
o.on("--setup [rails root path]") { |path| OPTIONS[:Setup] = path || "./" }
|
66
|
+
|
67
|
+
o.on_tail("--copy", "Display copyright information") {
|
68
|
+
puts "#{script_name} v#{Engines::VERSION::STRING}. Released under the MIT license."
|
69
|
+
puts "See http://wiki.oriontransfer.org/?rails:engines for more information."
|
70
|
+
|
71
|
+
exit
|
72
|
+
}
|
73
|
+
|
74
|
+
o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
|
75
|
+
|
76
|
+
o
|
77
|
+
end.parse!
|
78
|
+
|
79
|
+
if OPTIONS[:Setup]
|
80
|
+
config_path = File.join(OPTIONS[:Setup], "config", "environment.rb")
|
81
|
+
abort "#{config_path} does not exist. Is #{OPTIONS[:Setup]} a rails root directory?" unless File.exist? config_path
|
82
|
+
|
83
|
+
rake_text = <<EOF
|
84
|
+
|
85
|
+
require RAILS_ROOT + "/config/environment"
|
86
|
+
|
87
|
+
if defined? Engines
|
88
|
+
Engines.load_plugin_tasks
|
89
|
+
end
|
90
|
+
|
91
|
+
EOF
|
92
|
+
|
93
|
+
rake_path = File.join(OPTIONS[:Setup], "lib", "tasks", "load_plugin_tasks.rake")
|
94
|
+
unless File.exists?(rake_path)
|
95
|
+
File.open(rake_path, "w") { |f| f.write(rake_text) }
|
96
|
+
else
|
97
|
+
puts "#{rake_path} already exists, not overwriting."
|
98
|
+
end
|
99
|
+
|
100
|
+
insert_lines(["gem 'ioquatix-engines', Rails::VERSION::STRING", "require 'engines'"],
|
101
|
+
:into => 'config/environment.rb',
|
102
|
+
:after => "require File.join(File.dirname(__FILE__), 'boot')")
|
103
|
+
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,78 @@
|
|
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
|
+
ensure_schema_table_exists
|
9
|
+
get_plugins_to_migrate(runtime_args)
|
10
|
+
|
11
|
+
if @plugins_to_migrate.empty?
|
12
|
+
puts "All plugins are migrated to their latest versions"
|
13
|
+
exit(0)
|
14
|
+
end
|
15
|
+
|
16
|
+
@options[:migration_file_name] = build_migration_name
|
17
|
+
@options[:assigns][:class_name] = build_migration_name.classify
|
18
|
+
end
|
19
|
+
|
20
|
+
def manifest
|
21
|
+
record do |m|
|
22
|
+
m.migration_template 'plugin_migration.erb', 'db/migrate', @options
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# Create the schema table if it doesn't already exist.
|
29
|
+
def ensure_schema_table_exists
|
30
|
+
ActiveRecord::Base.connection.initialize_schema_migrations_table
|
31
|
+
end
|
32
|
+
|
33
|
+
# Determine all the plugins which have migrations that aren't present
|
34
|
+
# according to the plugin schema information from the database.
|
35
|
+
def get_plugins_to_migrate(plugin_names)
|
36
|
+
|
37
|
+
# First, grab all the plugins which exist and have migrations
|
38
|
+
@plugins_to_migrate = if plugin_names.empty?
|
39
|
+
Engines.plugins
|
40
|
+
else
|
41
|
+
plugin_names.map do |name|
|
42
|
+
Engines.plugins[name] ? Engines.plugins[name] : raise("Cannot find the plugin '#{name}'")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@plugins_to_migrate.reject! { |p| p.latest_migration.nil? }
|
47
|
+
|
48
|
+
# Then find the current versions from the database
|
49
|
+
@current_versions = {}
|
50
|
+
@plugins_to_migrate.each do |plugin|
|
51
|
+
@current_versions[plugin.name] = Engines::Plugin::Migrator.current_version(plugin)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Then find the latest versions from their migration directories
|
55
|
+
@new_versions = {}
|
56
|
+
@plugins_to_migrate.each do |plugin|
|
57
|
+
@new_versions[plugin.name] = plugin.latest_migration
|
58
|
+
end
|
59
|
+
|
60
|
+
# Remove any plugins that don't need migration
|
61
|
+
@plugins_to_migrate.map { |p| p.name }.each do |name|
|
62
|
+
@plugins_to_migrate.delete(Engines.plugins[name]) if @current_versions[name] == @new_versions[name]
|
63
|
+
end
|
64
|
+
|
65
|
+
@options[:assigns][:plugins] = @plugins_to_migrate
|
66
|
+
@options[:assigns][:new_versions] = @new_versions
|
67
|
+
@options[:assigns][:current_versions] = @current_versions
|
68
|
+
end
|
69
|
+
|
70
|
+
# Construct a unique migration name based on the plugins involved and the
|
71
|
+
# versions they should reach after this migration is run. The name constructed
|
72
|
+
# needs to be lowercase
|
73
|
+
def build_migration_name
|
74
|
+
@plugins_to_migrate.map do |plugin|
|
75
|
+
"#{plugin.name}_to_version_#{@new_versions[plugin.name]}"
|
76
|
+
end.join("_and_").downcase
|
77
|
+
end
|
78
|
+
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/lib/engines.rb
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
begin
|
2
|
+
require 'rails/version'
|
3
|
+
|
4
|
+
unless Rails::VERSION::STRING == "2.1.0"
|
5
|
+
raise "This version of the engines plugin requires Rails 2.1.0! Sorry!"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'set'
|
10
|
+
require 'active_support'
|
11
|
+
require File.join(File.dirname(__FILE__), 'engines/version')
|
12
|
+
require File.join(File.dirname(__FILE__), 'engines/plugin')
|
13
|
+
require File.join(File.dirname(__FILE__), 'engines/plugin/list')
|
14
|
+
require File.join(File.dirname(__FILE__), 'engines/assets')
|
15
|
+
require File.join(File.dirname(__FILE__), 'engines/rails_extensions/routing')
|
16
|
+
|
17
|
+
# == Parameters
|
18
|
+
#
|
19
|
+
# The Engines module has a number of public configuration parameters:
|
20
|
+
#
|
21
|
+
# [+public_directory+] The directory into which plugin assets should be
|
22
|
+
# mirrored. Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
|
23
|
+
# [+schema_info_table+] The table to use when storing plugin migration
|
24
|
+
# version information. Defaults to +plugin_schema_info+.
|
25
|
+
#
|
26
|
+
# Additionally, there are a few flags which control the behaviour of
|
27
|
+
# some of the features the engines plugin adds to Rails:
|
28
|
+
#
|
29
|
+
# [+disable_application_view_loading+] A boolean flag determining whether
|
30
|
+
# or not views should be loaded from
|
31
|
+
# the main <tt>app/views</tt> directory.
|
32
|
+
# Defaults to false; probably only
|
33
|
+
# useful when testing your plugin.
|
34
|
+
# [+disable_application_code_loading+] A boolean flag determining whether
|
35
|
+
# or not to load controllers/helpers
|
36
|
+
# from the main +app+ directory,
|
37
|
+
# if corresponding code exists within
|
38
|
+
# a plugin. Defaults to false; again,
|
39
|
+
# probably only useful when testing
|
40
|
+
# your plugin.
|
41
|
+
# [+disable_code_mixing+] A boolean flag indicating whether all plugin
|
42
|
+
# copies of a particular controller/helper should
|
43
|
+
# be loaded and allowed to override each other,
|
44
|
+
# or if the first matching file should be loaded
|
45
|
+
# instead. Defaults to false.
|
46
|
+
#
|
47
|
+
module Engines
|
48
|
+
# The set of all loaded plugins
|
49
|
+
mattr_accessor :plugins
|
50
|
+
self.plugins = Engines::Plugin::List.new
|
51
|
+
|
52
|
+
# List of extensions to load, can be changed in init.rb before calling Engines.init
|
53
|
+
mattr_accessor :rails_extensions
|
54
|
+
self.rails_extensions = %w(action_mailer asset_helpers dependencies)
|
55
|
+
|
56
|
+
# The name of the public directory to mirror public engine assets into.
|
57
|
+
# Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
|
58
|
+
mattr_accessor :public_directory
|
59
|
+
self.public_directory = File.join(RAILS_ROOT, 'public', 'plugin_assets')
|
60
|
+
|
61
|
+
# The table in which to store plugin schema information. Defaults to
|
62
|
+
# "plugin_schema_info".
|
63
|
+
mattr_accessor :schema_info_table
|
64
|
+
self.schema_info_table = "plugin_schema_info"
|
65
|
+
|
66
|
+
#--
|
67
|
+
# These attributes control the behaviour of the engines extensions
|
68
|
+
#++
|
69
|
+
|
70
|
+
# Set this to true if views should *only* be loaded from plugins
|
71
|
+
mattr_accessor :disable_application_view_loading
|
72
|
+
self.disable_application_view_loading = false
|
73
|
+
|
74
|
+
# Set this to true if controller/helper code shouldn't be loaded
|
75
|
+
# from the application
|
76
|
+
mattr_accessor :disable_application_code_loading
|
77
|
+
self.disable_application_code_loading = false
|
78
|
+
|
79
|
+
# Set this ti true if code should not be mixed (i.e. it will be loaded
|
80
|
+
# from the first valid path on $LOAD_PATH)
|
81
|
+
mattr_accessor :disable_code_mixing
|
82
|
+
self.disable_code_mixing = false
|
83
|
+
|
84
|
+
# This is used to determine which files are candidates for the "code
|
85
|
+
# mixing" feature that the engines plugin provides, where classes from
|
86
|
+
# plugins can be loaded, and then code from the application loaded
|
87
|
+
# on top of that code to override certain methods.
|
88
|
+
mattr_accessor :code_mixing_file_types
|
89
|
+
self.code_mixing_file_types = %w(controller helper)
|
90
|
+
|
91
|
+
class << self
|
92
|
+
def init
|
93
|
+
load_extensions
|
94
|
+
Engines::Assets.initialize_base_public_directory
|
95
|
+
end
|
96
|
+
|
97
|
+
def load_plugin_tasks
|
98
|
+
# Load any rake tasks that may not have been loaded from external plugins.
|
99
|
+
Engines.plugins.each do |plugin|
|
100
|
+
Dir["#{plugin.tasks_path}/**/*.rake"].sort.each { |ext| load ext }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def logger
|
105
|
+
RAILS_DEFAULT_LOGGER
|
106
|
+
end
|
107
|
+
|
108
|
+
def load_extensions
|
109
|
+
rails_extensions.each { |name| require "engines/rails_extensions/#{name}" }
|
110
|
+
# load the testing extensions, if we are in the test environment.
|
111
|
+
require "engines/testing" if RAILS_ENV == "test"
|
112
|
+
end
|
113
|
+
|
114
|
+
def select_existing_paths(paths)
|
115
|
+
paths.select { |path| File.directory?(path) }
|
116
|
+
end
|
117
|
+
|
118
|
+
# The engines plugin will, by default, mix code from controllers and helpers,
|
119
|
+
# allowing application code to override specific methods in the corresponding
|
120
|
+
# controller or helper classes and modules. However, if other file types should
|
121
|
+
# also be mixed like this, they can be added by calling this method. For example,
|
122
|
+
# if you want to include "things" within your plugin and override them from
|
123
|
+
# your applications, you should use the following layout:
|
124
|
+
#
|
125
|
+
# app/
|
126
|
+
# +-- things/
|
127
|
+
# | +-- one_thing.rb
|
128
|
+
# | +-- another_thing.rb
|
129
|
+
# ...
|
130
|
+
# vendor/
|
131
|
+
# +-- plugins/
|
132
|
+
# +-- my_plugin/
|
133
|
+
# +-- app/
|
134
|
+
# +-- things/
|
135
|
+
# +-- one_thing.rb
|
136
|
+
# +-- another_thing.rb
|
137
|
+
#
|
138
|
+
# The important point here is that your "things" are named <whatever>_thing.rb,
|
139
|
+
# and that they are placed within plugin/app/things (the pluralized form of 'thing').
|
140
|
+
#
|
141
|
+
# It's important to note that you'll also want to ensure that the "things" are
|
142
|
+
# on your load path in your plugin's init.rb:
|
143
|
+
#
|
144
|
+
# Engines.plugins[:my_plugin].code_paths << "app/things"
|
145
|
+
#
|
146
|
+
def mix_code_from(*types)
|
147
|
+
self.code_mixing_file_types += types.map { |x| x.to_s.singularize }
|
148
|
+
end
|
149
|
+
|
150
|
+
# A general purpose method to mirror a directory (+source+) into a destination
|
151
|
+
# directory, including all files and subdirectories. Files will not be mirrored
|
152
|
+
# if they are identical already (checked via FileUtils#identical?).
|
153
|
+
def mirror_files_from(source, destination)
|
154
|
+
return unless File.directory?(source)
|
155
|
+
|
156
|
+
# TODO: use Rake::FileList#pathmap?
|
157
|
+
source_files = Dir[source + "/**/*"]
|
158
|
+
source_dirs = source_files.select { |d| File.directory?(d) }
|
159
|
+
source_files -= source_dirs
|
160
|
+
|
161
|
+
source_dirs.each do |dir|
|
162
|
+
# strip down these paths so we have simple, relative paths we can
|
163
|
+
# add to the destination
|
164
|
+
target_dir = File.join(destination, dir.gsub(source, ''))
|
165
|
+
|
166
|
+
begin
|
167
|
+
FileUtils.mkdir_p(target_dir)
|
168
|
+
rescue Exception => e
|
169
|
+
raise "Could not create directory #{target_dir}: \n" + e
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
source_files.each do |file|
|
174
|
+
begin
|
175
|
+
target = File.join(destination, file.gsub(source, ''))
|
176
|
+
unless File.exist?(target) && FileUtils.identical?(file, target)
|
177
|
+
FileUtils.cp(file, target)
|
178
|
+
end
|
179
|
+
rescue Exception => e
|
180
|
+
raise "Could not copy #{file} to #{target}: \n" + e
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
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
|