r3_plugin_toolbox 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|