r3_plugin_toolbox 0.3.5 → 0.3.6
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/.document +0 -0
- data/.gitignore +0 -0
- data/.rspec +0 -0
- data/LICENSE +0 -0
- data/README.markdown +11 -6
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/config/database.yml +0 -0
- data/lib/r3_plugin_toolbox.rb +1 -1
- data/lib/r3_plugin_toolbox/engine.rb +77 -0
- data/lib/r3_plugin_toolbox/extender.rb +72 -0
- data/lib/r3_plugin_toolbox/extender/load_handler.rb +39 -0
- data/lib/r3_plugin_toolbox/extender/util.rb +64 -0
- data/lib/r3_plugin_toolbox/main.rb +5 -0
- data/lib/r3_plugin_toolbox/railtie.rb +85 -0
- data/lib/r3_plugin_toolbox/rspec/config.rb +14 -0
- data/lib/r3_plugin_toolbox/rspec/macro.rb +33 -0
- data/lib/r3_plugin_toolbox/rspec/matchers/be_extended_with.rb +66 -0
- data/lib/r3_plugin_toolbox/shortcuts.rb +11 -0
- data/log/development.log +0 -0
- data/r3_plugin_toolbox.gemspec +30 -16
- data/spec/fixtures/extension_modules.rb +29 -0
- data/spec/r3_plugin_toolbox/engine_spec.rb +17 -0
- data/spec/{plugin_toolbox → r3_plugin_toolbox/extender}/extend_view_content_spec.rb +5 -2
- data/spec/{plugin_toolbox → r3_plugin_toolbox/extender}/extender_action_spec.rb +4 -4
- data/spec/{plugin_toolbox → r3_plugin_toolbox/extender}/extender_i18n_spec.rb +2 -2
- data/spec/{plugin_toolbox → r3_plugin_toolbox}/extender_spec.rb +3 -3
- data/spec/r3_plugin_toolbox/railtie_spec.rb +16 -0
- data/spec/r3_plugin_toolbox/shortcuts_spec.rb +54 -0
- data/spec/spec_helper.rb +3 -32
- data/wiki/add_rake_tasks.markdown +0 -0
- data/wiki/engine.markdown +0 -0
- data/wiki/how_to_guide.markdown +0 -0
- metadata +49 -21
- data/lib/plugin_toolbox/extender.rb +0 -65
- data/lib/plugin_toolbox/loader.rb +0 -32
- data/lib/plugin_toolbox/rspec/config.rb +0 -12
- data/lib/plugin_toolbox/rspec/macro.rb +0 -32
- data/lib/plugin_toolbox/rspec/matchers/be_extended_with.rb +0 -64
- data/lib/plugin_toolbox/util.rb +0 -62
- data/rails3_plugin_toolbox.gemspec +0 -78
data/.document
CHANGED
File without changes
|
data/.gitignore
CHANGED
File without changes
|
data/.rspec
CHANGED
File without changes
|
data/LICENSE
CHANGED
File without changes
|
data/README.markdown
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
# Rails3 Plugin Toolbox
|
2
3
|
|
3
4
|
This is a small toolbox that greatly facilitates creating Plugins for Rails 3 without having to know a lot about the Rails 3 internals and Plugin architecture.
|
4
5
|
The toolbox provides a convenient DSL that abstracts away the internal Rails 3 plugin wiring to an even greater extent, making the DSL dead simple to use!
|
5
6
|
|
6
7
|
I also provide a specialized RSpec 2 matcher *be_extended_with* which makes it easy to spec your plugin extension functionality, to make sure Rails is extended with
|
7
|
-
the functionality (modules) that you expect and desire ;)
|
8
|
+
the functionality (modules) that you expect and desire ;)
|
9
|
+
|
10
|
+
Good description of the Rails 3 plugin structure on this gist by Jose Valim:
|
11
|
+
|
12
|
+
_INFO_: [Rails 3 plugin architecture](https://gist.github.com/af7e572c2dc973add221)
|
8
13
|
|
9
14
|
## Install
|
10
15
|
|
@@ -18,7 +23,7 @@ the functionality (modules) that you expect and desire ;)
|
|
18
23
|
require 'rails/all'
|
19
24
|
require 'r3_plugin_toolbox'
|
20
25
|
|
21
|
-
Rails3::
|
26
|
+
Rails3::Plugin::Extender.new do
|
22
27
|
extend_from_module Ultra::View, :stuff, :in => :view
|
23
28
|
extend_with Ultra::Controller, :in => :controller
|
24
29
|
|
@@ -52,7 +57,7 @@ end
|
|
52
57
|
More API examples
|
53
58
|
|
54
59
|
<pre>
|
55
|
-
Rails3::
|
60
|
+
Rails3::Plugin::Extender.new do
|
56
61
|
extend_rails :view do # or use :action_view
|
57
62
|
with MyViewAddition
|
58
63
|
end
|
@@ -100,7 +105,7 @@ require 'rails/all'
|
|
100
105
|
|
101
106
|
describe "My Plugin rails extensions" do
|
102
107
|
it "should extend Action View with View Helpers" do
|
103
|
-
Rails3::
|
108
|
+
Rails3::Plugin::Extender.new do
|
104
109
|
extend_rails :view do
|
105
110
|
extend_from_module Helper::View, :panel, :window
|
106
111
|
extend_with Helper::View::Button, Helper::View::Form
|
@@ -127,7 +132,7 @@ end
|
|
127
132
|
|
128
133
|
describe "My other Plugin rails extensions" do
|
129
134
|
before :each do
|
130
|
-
Rails3::
|
135
|
+
Rails3::Plugin::Extender.new do
|
131
136
|
extend_rails :view do
|
132
137
|
extend_from_module Helper::View, :grid, :tree
|
133
138
|
end
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.6
|
data/config/database.yml
CHANGED
File without changes
|
data/lib/r3_plugin_toolbox.rb
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
# See: http://edgeapi.rubyonrails.org/classes/Rails/Engine.html
|
2
|
+
|
3
|
+
# Any Rails::Engine is also a Rails::Railtie, so the same methods (like rake_tasks and generators) and configuration available in the latter can also be used in the former.
|
4
|
+
|
5
|
+
require 'r3_plugin_toolbox/railtie'
|
6
|
+
|
7
|
+
def make_engine module_name
|
8
|
+
eval %{
|
9
|
+
module #{module_name}
|
10
|
+
class Engine < ::Rails::Engine
|
11
|
+
extend ::Rails3::Engine::Assist
|
12
|
+
end
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
module Rails3
|
18
|
+
class Engine < ::Rails3::Plugin
|
19
|
+
attr_reader :name
|
20
|
+
|
21
|
+
def initialize name, &block
|
22
|
+
@name = name
|
23
|
+
module_name = name.to_s.camelize
|
24
|
+
make_engine module_name
|
25
|
+
|
26
|
+
engine = "#{module_name}::Engine".constantize
|
27
|
+
|
28
|
+
if block
|
29
|
+
block.arity < 1 ? engine.instance_eval(&block) : block.call(engine)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module Assist
|
34
|
+
include ::Rails3::Plugin::Assist
|
35
|
+
|
36
|
+
[:autoload, :eagerload].each do |name|
|
37
|
+
class_eval %{
|
38
|
+
def add_#{name}_paths path
|
39
|
+
config.#{name}_paths << path
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
[:controllers, :helpers, :models, :views].each do |name|
|
45
|
+
class_eval %{
|
46
|
+
def add_#{name}_dir path
|
47
|
+
paths.app.#{name} << path
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
[:initializers, :locales, :routes].each do |name|
|
53
|
+
class_eval %{
|
54
|
+
def add_#{name}_dir path
|
55
|
+
paths.config.#{name} << path
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_tasks_dir path
|
61
|
+
paths.lib.tasks << path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Example
|
68
|
+
|
69
|
+
# class MyEngine < Rails::Engine
|
70
|
+
# # Add a load path for this specific Engine
|
71
|
+
# config.autoload_paths << File.expand_path("../lib/some/path", __FILE__)
|
72
|
+
#
|
73
|
+
# initializer "my_engine.add_middleware" do |app|
|
74
|
+
# app.middleware.use MyEngine::Middleware
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'r3_plugin_toolbox/extender/util'
|
2
|
+
require 'r3_plugin_toolbox/extender/load_handler'
|
3
|
+
|
4
|
+
module Rails3
|
5
|
+
class Plugin
|
6
|
+
class Extender
|
7
|
+
include LoadHandler
|
8
|
+
|
9
|
+
def initialize &block
|
10
|
+
if block
|
11
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# load after: [:initialize, :configuration, :eager_load]
|
16
|
+
def extend_rails(type, &block)
|
17
|
+
on_load(type, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# convenience method to extend with multiple modules all within the same base module
|
22
|
+
def extend_from_module base_name, *module_names, options
|
23
|
+
raise ArgumentError, "You must specify an options Hash as the last argument for #extend_from_module" if !options.kind_of? Hash
|
24
|
+
module_names.each do |name|
|
25
|
+
extend_with get_constant(base_name, name), options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extend_with *module_names, options
|
30
|
+
raise ArgumentError, "You must specify an options Hash as the last argument for #extend_with" if !options.kind_of? Hash
|
31
|
+
type = options[:in]
|
32
|
+
raise ArgumentError, "You must specify an :in option to indicate which Rails 3 component base class to extend with #{module_names}" if !type
|
33
|
+
module_names.each do |name|
|
34
|
+
extend! name, type
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module DSL
|
39
|
+
include ::Rails3::Plugin::Extender::LoadHandler
|
40
|
+
|
41
|
+
def extend_from_module base_name, *module_names
|
42
|
+
module_names.each do |name|
|
43
|
+
include get_constant(base_name, name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def extend_with *module_names
|
48
|
+
module_names.each do |module_name|
|
49
|
+
begin
|
50
|
+
include get_module(module_name)
|
51
|
+
rescue
|
52
|
+
raise ArgumentError, "Unable to extend with #{module_name}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
alias_method :with, :extend_with
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def extend! module_name, type
|
62
|
+
do_extend! get_module(module_name), get_load_type(type.to_sym)
|
63
|
+
end
|
64
|
+
|
65
|
+
def do_extend! module_name, type
|
66
|
+
ActiveSupport.on_load(type) do
|
67
|
+
include module_name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'r3_plugin_toolbox/extender/util'
|
2
|
+
|
3
|
+
module Rails3
|
4
|
+
class Plugin
|
5
|
+
class Extender
|
6
|
+
module LoadHandler
|
7
|
+
include ::Rails3::Plugin::Extender::Util
|
8
|
+
|
9
|
+
def before type, &block
|
10
|
+
type = type.to_sym
|
11
|
+
raise ArgumentError, "#{type} is not a valid before hook" if !valid_before_hook? type
|
12
|
+
load_handling :"before_#{type}", &block
|
13
|
+
end
|
14
|
+
|
15
|
+
def after type, &block
|
16
|
+
type = type.to_sym
|
17
|
+
raise ArgumentError, "#{type} is not a valid after hook" if !valid_after_hook? type
|
18
|
+
load_handling :"after_#{type}", &block
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_load type, &block
|
22
|
+
type = get_load_type type
|
23
|
+
raise ArgumentError, "#{type} is not a valid load hook" if !valid_load_hook? type
|
24
|
+
load_handling type, &block
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_handling type, &block
|
28
|
+
ActiveSupport.on_load type do
|
29
|
+
extend Rails3::Plugin::Extender::DSL
|
30
|
+
|
31
|
+
if block
|
32
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Rails3
|
2
|
+
class Plugin
|
3
|
+
class Extender
|
4
|
+
module Util
|
5
|
+
INIT = :initialize
|
6
|
+
ACTIVE_MODULES = {:AR => :active_record, :view => :action_view, :controller => :action_controller, :mailer => :action_mailer}
|
7
|
+
|
8
|
+
def get_base_class type
|
9
|
+
type = get_load_type(type).to_s
|
10
|
+
const = act_type?(type) ? rails_const_base(type) : "#{type.to_s.camelize}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def act_type? type
|
14
|
+
type =~/action/ || type =~/active/
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_constant base_name, name
|
18
|
+
make_constant(base_name, name).constantize
|
19
|
+
end
|
20
|
+
|
21
|
+
def rails_const_base type
|
22
|
+
"#{type.to_s.camelize}::Base"
|
23
|
+
end
|
24
|
+
|
25
|
+
def make_constant base_name, name
|
26
|
+
"#{base_name.to_s.camelize}::#{name.to_s.camelize}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_load_type type
|
30
|
+
return ACTIVE_MODULES[type] if ACTIVE_MODULES[type]
|
31
|
+
return type if ACTIVE_MODULES.values.include? type
|
32
|
+
return type if type == :i18n
|
33
|
+
logger.warn "WARNING: The Rails 3 load handler for the component #{type} is not part of the default load process."
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_module module_name
|
37
|
+
case module_name
|
38
|
+
when Module
|
39
|
+
module_name
|
40
|
+
when String
|
41
|
+
module_name.to_s.constantize
|
42
|
+
else
|
43
|
+
raise ArgumentError, "#{module_name} could not be converted into a module constant"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def valid_before_hook? type
|
50
|
+
[INIT, :configuration, :eager_load].include?(type)
|
51
|
+
end
|
52
|
+
|
53
|
+
def valid_after_hook? type
|
54
|
+
INIT == type
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid_load_hook? type
|
58
|
+
@valid_load_hooks ||= [ACTIVE_MODULES.keys, ACTIVE_MODULES.values, :i18n].flatten
|
59
|
+
@valid_load_hooks.include?(type)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# See: http://edgeapi.rubyonrails.org/classes/Rails/Railtie.html
|
2
|
+
|
3
|
+
# Add a to_prepare block which is executed once in production
|
4
|
+
# and before each request in development
|
5
|
+
# config.to_prepare do
|
6
|
+
# MyRailtie.setup!
|
7
|
+
# end
|
8
|
+
|
9
|
+
# rake_tasks do
|
10
|
+
# load "path/to/my_railtie.tasks"
|
11
|
+
# end
|
12
|
+
|
13
|
+
# generators do
|
14
|
+
# require "path/to/my_railtie_generator"
|
15
|
+
# end
|
16
|
+
|
17
|
+
|
18
|
+
def make_railtie name
|
19
|
+
eval %{
|
20
|
+
module #{name.to_s.camelize}
|
21
|
+
class Railtie < Rails::Railtie
|
22
|
+
extend ::Rails3::Plugin::Assist
|
23
|
+
end
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
module Rails3
|
29
|
+
class Plugin
|
30
|
+
attr_reader :name
|
31
|
+
|
32
|
+
def initialize name, &block
|
33
|
+
@name = name
|
34
|
+
|
35
|
+
module_name = name.to_s.camelize
|
36
|
+
make_railtie module_name
|
37
|
+
|
38
|
+
railtie = "#{module_name}::Railtie".constantize
|
39
|
+
|
40
|
+
if block
|
41
|
+
block.arity < 1 ? railtie.instance_eval(&block) : block.call(railtie)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Assist
|
46
|
+
def set_test_framework name
|
47
|
+
config.generators.test_framework name
|
48
|
+
end
|
49
|
+
|
50
|
+
def use_middleware middleware
|
51
|
+
app.middleware.use middleware
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_orm orm_name
|
55
|
+
config.generators.orm(orm_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def subscribe_notifications *args, &block
|
59
|
+
ActiveSupport::Notifications.subscribe do |*args|
|
60
|
+
yield *args
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Example
|
68
|
+
|
69
|
+
# module NewPlugin
|
70
|
+
# # namespace our plugin and inherit from Rails::Railtie
|
71
|
+
# # to get our plugin into the initialization process
|
72
|
+
# class Railtie < Rails::Railtie
|
73
|
+
#
|
74
|
+
# # configure our plugin on boot. other extension points such
|
75
|
+
# # as configuration, rake tasks, etc, are also available
|
76
|
+
# initializer "newplugin.initialize" do |app|
|
77
|
+
#
|
78
|
+
# # subscribe to all rails notifications: controllers, AR, etc.
|
79
|
+
# ActiveSupport::Notifications.subscribe do |*args|
|
80
|
+
# event = ActiveSupport::Notifications::Event.new(*args)
|
81
|
+
# puts "Got notification: #{event.inspect}"
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
# end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'r3_plugin_toolbox/rspec/macro'
|
3
|
+
require_all File.dirname(__FILE__) + '/matchers'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.include Rails3::Plugin::Extender::Matchers
|
7
|
+
config.extend Rails3::Plugin::Extender::Macro
|
8
|
+
end
|
9
|
+
|
10
|
+
module RSpec::Core
|
11
|
+
class ExampleGroup
|
12
|
+
include Rails3::Plugin::Extender::Macro
|
13
|
+
end
|
14
|
+
end
|