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.
Files changed (41) hide show
  1. data/.document +0 -0
  2. data/.gitignore +0 -0
  3. data/.rspec +0 -0
  4. data/LICENSE +0 -0
  5. data/README.markdown +11 -6
  6. data/Rakefile +1 -0
  7. data/VERSION +1 -1
  8. data/config/database.yml +0 -0
  9. data/lib/r3_plugin_toolbox.rb +1 -1
  10. data/lib/r3_plugin_toolbox/engine.rb +77 -0
  11. data/lib/r3_plugin_toolbox/extender.rb +72 -0
  12. data/lib/r3_plugin_toolbox/extender/load_handler.rb +39 -0
  13. data/lib/r3_plugin_toolbox/extender/util.rb +64 -0
  14. data/lib/r3_plugin_toolbox/main.rb +5 -0
  15. data/lib/r3_plugin_toolbox/railtie.rb +85 -0
  16. data/lib/r3_plugin_toolbox/rspec/config.rb +14 -0
  17. data/lib/r3_plugin_toolbox/rspec/macro.rb +33 -0
  18. data/lib/r3_plugin_toolbox/rspec/matchers/be_extended_with.rb +66 -0
  19. data/lib/r3_plugin_toolbox/shortcuts.rb +11 -0
  20. data/log/development.log +0 -0
  21. data/r3_plugin_toolbox.gemspec +30 -16
  22. data/spec/fixtures/extension_modules.rb +29 -0
  23. data/spec/r3_plugin_toolbox/engine_spec.rb +17 -0
  24. data/spec/{plugin_toolbox → r3_plugin_toolbox/extender}/extend_view_content_spec.rb +5 -2
  25. data/spec/{plugin_toolbox → r3_plugin_toolbox/extender}/extender_action_spec.rb +4 -4
  26. data/spec/{plugin_toolbox → r3_plugin_toolbox/extender}/extender_i18n_spec.rb +2 -2
  27. data/spec/{plugin_toolbox → r3_plugin_toolbox}/extender_spec.rb +3 -3
  28. data/spec/r3_plugin_toolbox/railtie_spec.rb +16 -0
  29. data/spec/r3_plugin_toolbox/shortcuts_spec.rb +54 -0
  30. data/spec/spec_helper.rb +3 -32
  31. data/wiki/add_rake_tasks.markdown +0 -0
  32. data/wiki/engine.markdown +0 -0
  33. data/wiki/how_to_guide.markdown +0 -0
  34. metadata +49 -21
  35. data/lib/plugin_toolbox/extender.rb +0 -65
  36. data/lib/plugin_toolbox/loader.rb +0 -32
  37. data/lib/plugin_toolbox/rspec/config.rb +0 -12
  38. data/lib/plugin_toolbox/rspec/macro.rb +0 -32
  39. data/lib/plugin_toolbox/rspec/matchers/be_extended_with.rb +0 -64
  40. data/lib/plugin_toolbox/util.rb +0 -62
  41. 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
- # Rails 3 Plugin Toolbox
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::PluginExtender.new do
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::PluginExtender.new do
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::PluginExtender.new do
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::PluginExtender.new do
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
@@ -9,6 +9,7 @@ begin
9
9
  gem.authors = ["Kristian Mandrup"]
10
10
  gem.add_development_dependency "rspec", "~> 2.0.0"
11
11
 
12
+ gem.add_development_dependency "rspec", ">= 2.0.0.beta.19"
12
13
  gem.add_dependency "rails", "~> 3.0.0"
13
14
  gem.add_dependency "require_all", "~> 1.1.0"
14
15
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.3.6
data/config/database.yml CHANGED
File without changes
@@ -4,4 +4,4 @@ end
4
4
  require 'active_support/inflector'
5
5
  require 'require_all'
6
6
 
7
- require_all File.dirname(__FILE__) + '/plugin_toolbox'
7
+ require_all File.dirname(__FILE__) + '/r3_plugin_toolbox'
@@ -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,5 @@
1
+ require 'r3_plugin_toolbox/railtie'
2
+ require 'r3_plugin_toolbox/extender'
3
+ require 'r3_plugin_toolbox/engine'
4
+
5
+ require_all File.dirname(__FILE__) + '/rspec'
@@ -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