rails3_plugin_toolbox 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  A toolbox to facilitate creating Plugins for Rails 3 without having to necessarily know a lot about the Rails 3 internals and Plugin architecture.
4
4
 
5
- ## Status
5
+ ## RSpec test suite
6
6
 
7
- This gem needs to be tested. I 'hope' it works as is... I will soon make sure of it and add an RSpec 2 test suite ;)
7
+ I have now discovered how to test he validity of Rails extensions in RSpec without having to have a full Rails 3 host app.
8
+ RSpec 2 test suite will soon be added :)
9
+
10
+ http://gist.github.com/542441
8
11
 
9
12
  ## Inspiration
10
13
 
@@ -19,47 +22,58 @@ This project was inspired by the Yehuda Katz article at http://www.railsdispatch
19
22
  <pre>
20
23
  # my_plugin/lib/load.rb
21
24
  module MyPlugin
22
- include Rails::Plugin::Toolbox::Extender
23
-
24
- # do some actions after Application has been initialized using registered initializers
25
- after(:initialize) do
26
- include MyViewModule
27
- end
28
-
29
- # extend action_view with methods from some modules
30
- extend_rails(:view) do
31
- with UltraFix
32
- with PowerTools
33
- end
25
+ Rails3::PluginExtender.new do
26
+
27
+ extend_from_module Ultra::View, :stuff, :in => :view
28
+ extend_with Ultra::Controller, :in => :controller
29
+
30
+ extend_rails :i18n do
31
+ with MyAddition
32
+ extend_from_module Ultra::Power, :util, :logging, :monitor
33
+
34
+ before :initialize do
35
+ MyOtherAddition.say 'before localized!'
36
+ end
37
+
38
+ before :configuration do
39
+ MyOtherAddition.configured = 'was configured!'
40
+ end
41
+
42
+ before :eager_load do
43
+ puts "before eager load!"
44
+ end
45
+
46
+ after :initialize do
47
+ MyAddition.say 'localized!'
48
+ end
49
+ end
34
50
 
35
- extend_rails(:controller) do
36
- extend_from_module Ultra::Power, :util, :logging, :monitor
37
- extend_from_module Ultra::Power::More, :extra, :stuff
38
- end
39
- end
40
- </pre>
51
+ extend_rails :view do
52
+ with MyViewAddition
53
+ end
41
54
 
42
- The following are some general tips for adding custom rake tasks and generators to your Rails 3 plugin.
55
+ extend_rails :controller do
56
+ with MyViewAddition
57
+ end
43
58
 
44
- ## Custom rake tasks
59
+ extend_rails :mailer do
60
+ with MyMailAddition, 'MyOtherMailAddition'
61
+ end
45
62
 
46
- <pre>
47
- # my_plugin/lib/railtie.rb
48
- module MyPlugin
49
- class Railtie < ::Rails::Railtie
50
- rake_tasks do
51
- load "my_plugin/railties/tasks.rake"
63
+ extend_rails :AR do
64
+ with MyActiveRecordAddition
52
65
  end
53
- end
54
- end
55
- </pre>
56
66
 
57
- <pre>
58
- # my_plugin/lib/railties/tasks.rake
59
- desc "Talk about being in my_gem"
60
- task :my_gem do
61
- puts "You're in my_gem"
62
- end
67
+ extend_rails(:controller) do
68
+ extend_from_module Ultra::Power, :util, :logging, :monitor
69
+ extend_from_module Ultra::Power::More, :extra, :stuff
70
+ end
71
+
72
+ after(:initialize) do
73
+ include MyCoreModule
74
+ end
75
+ end
76
+ end
63
77
  </pre>
64
78
 
65
79
 
data/Rakefile CHANGED
@@ -16,30 +16,3 @@ begin
16
16
  rescue LoadError
17
17
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
18
  end
19
-
20
- # require 'spec/rake/spectask'
21
- # Spec::Rake::SpecTask.new(:spec) do |spec|
22
- # spec.libs << 'lib' << 'spec'
23
- # spec.spec_files = FileList['spec/**/*_spec.rb']
24
- # end
25
- #
26
- # Spec::Rake::SpecTask.new(:rcov) do |spec|
27
- # spec.libs << 'lib' << 'spec'
28
- # spec.pattern = 'spec/**/*_spec.rb'
29
- # spec.rcov = true
30
- # end
31
- #
32
- # task :spec => :check_dependencies
33
- #
34
- # task :default => :spec
35
- #
36
- # require 'rake/rdoctask'
37
- # Rake::RDocTask.new do |rdoc|
38
- # version = File.exist?('VERSION') ? File.read('VERSION') : ""
39
- #
40
- # rdoc.rdoc_dir = 'rdoc'
41
- # rdoc.title = "rails3_plugin_toolbox #{version}"
42
- # rdoc.rdoc_files.include('README*')
43
- # rdoc.rdoc_files.include('lib/**/*.rb')
44
- # end
45
-
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -0,0 +1,22 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3-ruby (not necessary on OS X Leopard)
3
+ development:
4
+ adapter: sqlite3
5
+ database: db/development.sqlite3
6
+ pool: 5
7
+ timeout: 5000
8
+
9
+ # Warning: The database defined as "test" will be erased and
10
+ # re-generated from your development database when you run "rake".
11
+ # Do not set this db to the same as development or production.
12
+ test:
13
+ adapter: sqlite3
14
+ database: db/test.sqlite3
15
+ pool: 5
16
+ timeout: 5000
17
+
18
+ production:
19
+ adapter: sqlite3
20
+ database: db/production.sqlite3
21
+ pool: 5
22
+ timeout: 5000
@@ -1,45 +1,65 @@
1
1
  require 'plugin_toolbox/util'
2
2
 
3
- module Rails::PluginToolbox
4
- class Extender
5
- include Rails::PluginToolbox::Util
6
-
7
- attr_reader :loader
8
-
9
- def initialize
10
- @loader = Loader.new
3
+ module Rails3
4
+ class PluginExtender
5
+ include LoadHandler
6
+
7
+ def initialize &block
8
+ if block
9
+ block.arity < 1 ? self.instance_eval(&block) : block.call(self)
10
+ end
11
11
  end
12
-
12
+
13
+ # load after: [:initialize, :configuration, :eager_load]
13
14
  def extend_rails(type, &block)
14
- loader.load_after(type, &block)
15
- end
16
-
17
- def extend! module_name, type
18
- do_extend! get_module(module_name), get_type(type.to_sym)
15
+ on_load(type, &block)
19
16
  end
20
-
21
- def extend_with module_name
22
- type = options[:in] || options
23
- extend! module_name, type
24
- end
25
- alias_method :with, :extend_with
26
17
 
18
+
27
19
  # convenience method to extend with multiple modules all within the same base module
28
- def extend_from_module base_name, *module_names
20
+ def extend_from_module base_name, *module_names, options
21
+ raise ArgumentError, "You must specify an options Hash as the last argument for #extend_from_module" if !options.kind_of? Hash
29
22
  module_names.each do |name|
30
- extend_with "#{base_name.camelize}::#{name.to_s.camelize}".constantize
23
+ extend_with "#{base_name.camelize}::#{name.to_s.camelize}".constantize, options
24
+ end
25
+ end
26
+
27
+ def extend_with *module_names, options
28
+ raise ArgumentError, "You must specify an options Hash as the last argument for #extend_with" if !options.kind_of? Hash
29
+ type = options[:in]
30
+ raise ArgumentError, "You must specify an :in option to indicate which Rails 3 component base class to extend with #{module_names}" if !type
31
+ module_names.each do |name|
32
+ extend! name, type
31
33
  end
32
- type = options[:in] || options
33
- extend! module_name, type
34
- end
34
+ end
35
35
 
36
+ module DSL
37
+ include Rails3::PluginExtender::LoadHandler
38
+
39
+ def extend_from_module base_name, *module_names
40
+ module_names.each do |name|
41
+ include "#{base_name.camelize}::#{name.to_s.camelize}".constantize
42
+ end
43
+ end
44
+
45
+ def extend_with *module_names
46
+ module_names.each do |name|
47
+ include name
48
+ end
49
+ end
50
+ alias_method :with, :extend_with
51
+ end
52
+
36
53
  protected
37
-
54
+
55
+ def extend! module_name, type
56
+ do_extend! get_module(module_name), get_load_type(type.to_sym)
57
+ end
58
+
38
59
  def do_extend! module_name, type
39
60
  ActiveSupport.on_load(type) do
40
61
  include module_name
41
62
  end
42
- end
43
-
63
+ end
44
64
  end
45
65
  end
@@ -1,31 +1,32 @@
1
- require_all File.dirname(__FILE__) + '/validator'
1
+ module Rails3
2
+ class PluginExtender
3
+ module LoadHandler
4
+ include Rails3::PluginExtender::Util
2
5
 
3
- module Rails::PluginToolbox
4
- class Loader
5
- include Rails::PluginToolbox::HookValidator
6
-
7
- def load_before type, &block
8
- raise ArgumentError "#{type} is not a valid before hook" if !valid_before_hook?
9
- ActiveSupport.on_load(:"before_#{type}") do |loader|
10
- do_loader loader, &block
6
+ def before type, &block
7
+ type = type.to_sym
8
+ raise ArgumentError, "#{type} is not a valid before hook" if !valid_before_hook? type
9
+ load_handling :"before_#{type}", &block
11
10
  end
12
- end
13
11
 
14
- def load_after type, &block
15
- type = valid_after_hook? ? type : :"action_#{type}"
16
- raise ArgumentError "#{type} is not a valid after hook" if !valid_after_hook? type
17
- ActiveSupport.on_load(type) do |loader|
18
- do_loader loader, &block
12
+ def after type, &block
13
+ type = type.to_sym
14
+ raise ArgumentError, "#{type} is not a valid after hook" if !valid_after_hook? type
15
+ load_handling :"after_#{type}", &block
19
16
  end
20
- end
21
-
22
- protected
23
17
 
24
- def do_loader loader, &block
25
- loader.extend(Loader)
26
- if block
27
- block.arity < 1 ? loader.instance_eval(&block) : block.call(loader)
18
+ def on_load type, &block
19
+ type = get_load_type type
20
+ raise ArgumentError, "#{type} is not a valid load hook" if !valid_load_hook? type
21
+ load_handling type, &block
28
22
  end
29
- end
23
+
24
+ def load_handling type, &block
25
+ ActiveSupport.on_load type do
26
+ extend Rails3::PluginExtender::DSL
27
+ instance_eval(&block)
28
+ end
29
+ end
30
+ end
30
31
  end
31
32
  end
@@ -1,24 +1,41 @@
1
- require_all File.dirname(__FILE__) + '/validator'
1
+ module Rails3
2
+ class PluginExtender
3
+ module Util
4
+ INIT = :initialize
5
+ ACTIVE_MODULES = {:AR => :active_record, :view => :action_view, :controller => :action_controller, :mailer => :action_mailer}
6
+
7
+ def get_load_type type
8
+ return ACTIVE_MODULES[type] if ACTIVE_MODULES[type]
9
+ return type if ACTIVE_MODULES.values.include? type
10
+ return type if type == :i18n
11
+ logger.warn "WARNING: The Rails 3 load handler for the component #{type} is not part of the default load process."
12
+ end
13
+
14
+ def get_module module_name
15
+ case module_name
16
+ when Constant
17
+ module_name
18
+ when String
19
+ module_name.to_s.constantize
20
+ else
21
+ raise ArgumentError, "#{module_name} could not be converted into a module constant"
22
+ end
23
+ end
2
24
 
3
- module Rails::PluginToolbox
4
- module Util
5
- include Rails::PluginToolbox::TypeValidator
25
+ protected
6
26
 
7
- def get_type category
8
- return :"action_#{type}" if action_type?(type)
9
- return type if valid_type?(type)
10
- raise ArgumentError, "The type #{type} was not recognized"
11
- end
27
+ def valid_before_hook? type
28
+ [INIT, :configuration, :eager_load].include?(type)
29
+ end
12
30
 
13
- def get_module module_name
14
- case module_name
15
- when Constant
16
- module_name
17
- when String
18
- module_name.to_s.constantize
19
- else
20
- raise ArgumentError, "#{module_name} could not be converted into a loaded module"
31
+ def valid_after_hook? type
32
+ INIT == type
21
33
  end
34
+
35
+ def valid_load_hook? type
36
+ @valid_load_hooks ||= [ACTIVE_MODULES.keys, ACTIVE_MODULES.values, :i18n].flatten
37
+ @valid_load_hooks.include?(type)
38
+ end
22
39
  end
23
40
  end
24
41
  end
@@ -1,6 +1,5 @@
1
- module Rails
2
- module PluginToolbox
3
- end
1
+ module Rails3
4
2
  end
5
3
 
4
+ require 'require_all'
6
5
  require_all File.dirname(__FILE__) + '/plugin_toolbox'
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails3_plugin_toolbox}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kristian Mandrup"]
12
- s.date = %q{2010-08-21}
12
+ s.date = %q{2010-08-22}
13
13
  s.description = %q{Toolbox to facilitate Rails 3 plugin development}
14
14
  s.email = %q{kmandrup@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -24,17 +24,20 @@ Gem::Specification.new do |s|
24
24
  "README.markdown",
25
25
  "Rakefile",
26
26
  "VERSION",
27
+ "config/database.yml",
27
28
  "lib/plugin_toolbox/extender.rb",
28
29
  "lib/plugin_toolbox/loader.rb",
29
30
  "lib/plugin_toolbox/util.rb",
30
- "lib/plugin_toolbox/validator/hook_validator.rb",
31
- "lib/plugin_toolbox/validator/type_validator.rb",
32
31
  "lib/rails3_plugin_toolbox.rb",
32
+ "log/development.log",
33
33
  "rails3_plugin_toolbox.gemspec",
34
+ "spec/plugin_toolbox/extender_action_spec.rb",
35
+ "spec/plugin_toolbox/extender_i18n_spec.rb",
34
36
  "spec/plugin_toolbox/extender_spec.rb",
35
- "spec/plugin_toolbox/loader_spec.rb",
36
- "spec/plugin_toolbox/util_spec.rb",
37
- "spec/spec_helper.rb"
37
+ "spec/spec_helper.rb",
38
+ "wiki/add_rake_tasks.markdown",
39
+ "wiki/engine.markdown",
40
+ "wiki/how_to_guide.markdown"
38
41
  ]
39
42
  s.homepage = %q{http://github.com/kristianmandrup/rails3_plugin_toolbox}
40
43
  s.rdoc_options = ["--charset=UTF-8"]
@@ -42,9 +45,9 @@ Gem::Specification.new do |s|
42
45
  s.rubygems_version = %q{1.3.7}
43
46
  s.summary = %q{Toolbox to facilitate Rails 3 plugin development}
44
47
  s.test_files = [
45
- "spec/plugin_toolbox/extender_spec.rb",
46
- "spec/plugin_toolbox/loader_spec.rb",
47
- "spec/plugin_toolbox/util_spec.rb",
48
+ "spec/plugin_toolbox/extender_action_spec.rb",
49
+ "spec/plugin_toolbox/extender_i18n_spec.rb",
50
+ "spec/plugin_toolbox/extender_spec.rb",
48
51
  "spec/spec_helper.rb"
49
52
  ]
50
53
 
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails3::PluginExtender do
4
+ describe '#extend_rails' do
5
+ it "should extend Action View" do
6
+ extender = Rails3::PluginExtender.new
7
+ extender.extend_rails :view do
8
+ with MyAddition
9
+
10
+ after :initialize do
11
+ MyAddition.say 'view it!'
12
+ end
13
+ end
14
+
15
+ # Initialize the rails application
16
+ Minimal::Application.initialize!
17
+
18
+ ActionView::Base.instance_methods.grep(/zzz/).should_not be_empty
19
+
20
+ MyAddition.heard.should == 'view it!'
21
+ end
22
+
23
+ it "should extend Action Controller" do
24
+ Rails3::PluginExtender.new do
25
+ extend_rails :controller do
26
+ with MyAddition
27
+
28
+ after :initialize do
29
+ MyAddition.say 'control it!'
30
+ end
31
+ end
32
+ end
33
+
34
+ # Initialize the rails application
35
+ Minimal::Application.initialize!
36
+
37
+ ActionController::Base.instance_methods.grep(/zzz/).should_not be_empty
38
+
39
+ MyAddition.heard.should == 'control it!'
40
+ end
41
+
42
+ it "should extend Action Mailer" do
43
+ Rails3::PluginExtender.new do
44
+ extend_rails :mailer do
45
+ with MyAddition
46
+
47
+ after :initialize do
48
+ MyAddition.say 'mail me!'
49
+ end
50
+ end
51
+ end
52
+
53
+ # Initialize the rails application
54
+ Minimal::Application.initialize!
55
+
56
+ ActionMailer::Base.instance_methods.grep(/zzz/).should_not be_empty
57
+
58
+ MyAddition.heard.should == 'mail me!'
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails3::PluginExtender do
4
+ describe '#extend_rails' do
5
+ it "should extend i18n" do
6
+ Rails3::PluginExtender.new do
7
+ extend_rails :i18n do
8
+ with MyAddition
9
+
10
+ before :initialize do
11
+ MyOtherAddition.say 'before localized!'
12
+ end
13
+
14
+ before :configuration do
15
+ MyOtherAddition.configured = 'was configured!'
16
+ end
17
+
18
+ before :eager_load do
19
+ puts "before eager load!"
20
+ end
21
+
22
+ after :initialize do
23
+ MyAddition.say 'localized!'
24
+ end
25
+ end
26
+ end
27
+
28
+ # Initialize the rails application
29
+ Minimal::Application.initialize!
30
+ I18n.methods.grep(/zzz/).should_not be_empty
31
+
32
+ MyAddition.heard.should == 'localized!'
33
+ MyOtherAddition.heard.should == 'before localized!'
34
+ MyOtherAddition.configured.should == 'was configured!'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rails3::PluginExtender do
4
+ describe '#extend_rails' do
5
+ it "should NOT extend Unknown" do
6
+ lambda do
7
+ Rails3::PluginExtender.new
8
+ extend_rails :unknown do
9
+ with MyAddition
10
+ end
11
+ end
12
+ end.should raise_error
13
+
14
+ # Initialize the rails application
15
+ Minimal::Application.initialize!
16
+
17
+ MyAddition.heard.should == null
18
+ end
19
+
20
+ it "should extend Active Record" do
21
+ Rails3::PluginExtender.new do
22
+ extend_rails :AR do
23
+ with MyAddition
24
+
25
+ after :initialize do
26
+ MyAddition.say 'record me!'
27
+ end
28
+ end
29
+ end
30
+
31
+ # Initialize the rails application
32
+ Minimal::Application.initialize!
33
+
34
+ ActiveRecord::Base.instance_methods.grep(/zzz/).should_not be_empty
35
+
36
+ MyAddition.heard.should == 'record me!'
37
+ end
38
+ end
39
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,51 @@
1
1
  require 'rspec'
2
2
  require 'rspec/autorun'
3
+ require 'active_support'
4
+ require 'active_record'
5
+ require 'action_controller'
6
+ require 'action_view'
3
7
  require 'rails3_plugin_toolbox'
4
8
 
9
+ # See http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/
10
+
11
+ # require 'active_support/railtie'
12
+ require 'rails/all'
13
+
14
+ module Minimal
15
+ class Application < Rails::Application
16
+ config.active_support.deprecation = :log
17
+ end
18
+ end
19
+
20
+ module MyAddition
21
+ def zzz
22
+ 'zzz'
23
+ end
24
+
25
+ class << self
26
+ attr_accessor :heard
27
+
28
+ def say message
29
+ @heard = message
30
+ end
31
+ end
32
+ end
33
+
34
+ module MyOtherAddition
35
+ def yyy
36
+ 'yyy'
37
+ end
38
+
39
+ class << self
40
+ attr_accessor :heard
41
+ attr_accessor :configured
42
+
43
+ def say message
44
+ @heard = message
45
+ end
46
+ end
47
+ end
48
+
49
+
5
50
  RSpec.configure do |config|
6
-
7
51
  end
@@ -0,0 +1,22 @@
1
+ The following are some general tips for adding custom rake tasks and generators to your Rails 3 plugin.
2
+
3
+ ## Custom rake tasks
4
+
5
+ <pre>
6
+ # my_plugin/lib/railtie.rb
7
+ module MyPlugin
8
+ class Railtie < ::Rails::Railtie
9
+ rake_tasks do
10
+ load "my_plugin/railties/tasks.rake"
11
+ end
12
+ end
13
+ end
14
+ </pre>
15
+
16
+ <pre>
17
+ # my_plugin/lib/railties/tasks.rake
18
+ desc "Talk about being in my_gem"
19
+ task :my_gem do
20
+ puts "You're in my_gem"
21
+ end
22
+ </pre>
@@ -0,0 +1,52 @@
1
+ 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.
2
+
3
+ <pre>
4
+ class MyEngine < Rails::Engine
5
+ # Add a load path for this specific Engine
6
+ config.autoload_paths << File.expand_path("../lib/some/path", __FILE__)
7
+
8
+ initializer "my_engine.add_middleware" do |app|
9
+ app.middleware.use MyEngine::Middleware
10
+ end
11
+ end
12
+ </pre>
13
+
14
+ h2.Paths
15
+
16
+ Since Rails 3.0, both your Application and Engines do not have hardcoded paths. This means that you are not required to place your controllers at “app/controllers“, but in any place which you find convenient.
17
+
18
+ For example, let’s suppose you want to lay your controllers at lib/controllers, all you need to do is:
19
+
20
+ <pre>
21
+ class MyEngine < Rails::Engine
22
+ paths.app.controllers = "lib/controllers"
23
+ end
24
+
25
+ </pre>
26
+
27
+ You can also have your controllers being loaded from both “app/controllers“ and “lib/controllers“:
28
+
29
+ <pre>
30
+ class MyEngine < Rails::Engine
31
+ paths.app.controllers << "lib/controllers"
32
+ end
33
+ </pre>
34
+
35
+ The available paths in an Engine are:
36
+
37
+ <pre>
38
+ class MyEngine < Rails::Engine
39
+ paths.app = "app"
40
+ paths.app.controllers = "app/controllers"
41
+ paths.app.helpers = "app/helpers"
42
+ paths.app.models = "app/models"
43
+ paths.app.views = "app/views"
44
+ paths.lib = "lib"
45
+ paths.lib.tasks = "lib/tasks"
46
+ paths.config = "config"
47
+ paths.config.initializers = "config/initializers"
48
+ paths.config.locales = "config/locales"
49
+ paths.config.routes = "config/routes.rb"
50
+ end
51
+
52
+ </pre>
@@ -0,0 +1,153 @@
1
+ http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/
2
+
3
+ The documentation for Railtie is a great place to get started, but the interesting observation is that each of the major Rails components (Action Mailer/Controller/View/Record) is itself a Railtie, and Rails as you know it is simply pieced together by requiring all of the independent components. Even better, if your plugin or gem needs to hook into the Rails initialization process, all you need to do is inherit from Railtie and you are ready to go!
4
+
5
+ So how does Railtie know to call your classes and initializers? Railtie defines a self.inherited method, which is called anytime a subclass of Railtie is created, and stashes a reference to this class in a @subclasses variable. From there, the framework can simply call Railtie.subclasses and perform all the initialization as usual - a clever use of the Ruby object model.
6
+
7
+ module NewPlugin
8
+ # namespace our plugin and inherit from Rails::Railtie
9
+ # to get our plugin into the initialization process
10
+ class Railtie < Rails::Railtie
11
+
12
+ # configure our plugin on boot. other extension points such
13
+ # as configuration, rake tasks, etc, are also available
14
+ initializer "newplugin.initialize" do |app|
15
+
16
+ # subscribe to all rails notifications: controllers, AR, etc.
17
+ ActiveSupport::Notifications.subscribe do |*args|
18
+ event = ActiveSupport::Notifications::Event.new(*args)
19
+ puts "Got notification: #{event.inspect}"
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+
26
+ ---
27
+
28
+ Railtie is the core of the Rails Framework and provides several hooks to extend Rails and/or modify the initialization process.
29
+
30
+ Every major component of Rails (Action Mailer, Action Controller, Action View, Active Record and Active Resource) are all Railties, so each of them is responsible to set their own initialization. This makes, for example, Rails absent of any Active Record hook, allowing any other ORM framework to hook in.
31
+
32
+ Developing a Rails extension does not require any implementation of Railtie, but if you need to interact with the Rails framework during or after boot, then Railtie is what you need to do that interaction.
33
+
34
+ For example, the following would need you to implement Railtie in your plugin:
35
+
36
+ * creating initializers
37
+ * configuring a Rails framework or the Application, like setting a generator
38
+ * adding Rails config.* keys to the environment
39
+ * setting up a subscriber to the Rails +ActiveSupport::Notifications+
40
+ * adding rake tasks into rails
41
+
42
+ h2. Creating your Railtie
43
+
44
+ Implementing Railtie in your Rails extension is done by creating a class Railtie that has your extension name and making sure that this gets loaded during boot time of the Rails stack.
45
+
46
+ You can do this however you wish, but here is an example if you want to provide it for a gem that can be used with or without Rails:
47
+
48
+ * Create a file (say, lib/my_gem/railtie.rb) which contains class Railtie inheriting from Rails::Railtie and is namespaced to your gem:
49
+
50
+ <pre>
51
+ # lib/my_gem/railtie.rb
52
+ module MyGem
53
+ class Railtie < Rails::Railtie
54
+ end
55
+ end
56
+ </pre>
57
+
58
+ * Require your own gem as well as rails in this file:
59
+
60
+ <pre>
61
+ # lib/my_gem/railtie.rb
62
+ require 'my_gem'
63
+ require 'rails'
64
+
65
+ module MyGem
66
+ class Railtie < Rails::Railtie
67
+ end
68
+ end
69
+ </pre>
70
+
71
+ h2. Initializers
72
+
73
+ To add an initialization step from your Railtie to Rails boot process, you just need to create an initializer block:
74
+
75
+ <pre>
76
+ class MyRailtie < Rails::Railtie
77
+ initializer "my_railtie.configure_rails_initialization" do
78
+ # some initialization behavior
79
+ end
80
+ end
81
+ </pre>
82
+
83
+ If specified, the block can also receive the application object, in case you need to access some application specific configuration, like middleware:
84
+
85
+ <pre>
86
+ class MyRailtie < Rails::Railtie
87
+ initializer "my_railtie.configure_rails_initialization" do |app|
88
+ app.middleware.use MyRailtie::Middleware
89
+ end
90
+ end
91
+ </pre>
92
+
93
+ Finally, you can also pass :before and :after as option to initializer, in case you want to couple it with a specific step in the initialization process.
94
+ Configuration
95
+
96
+ Inside the Railtie class, you can access a config object which contains configuration shared by all railties and the application:
97
+
98
+ <pre>
99
+ class MyRailtie < Rails::Railtie
100
+ # Customize the ORM
101
+ config.generators.orm :my_railtie_orm
102
+
103
+ # Add a to_prepare block which is executed once in production
104
+ # and before each request in development
105
+ config.to_prepare do
106
+ MyRailtie.setup!
107
+ end
108
+ end
109
+ </pre>
110
+
111
+ Loading rake tasks and generators
112
+
113
+ If your railtie has rake tasks, you can tell Rails to load them through the method rake tasks:
114
+
115
+ <pre>
116
+ class MyRailtie < Railtie
117
+ rake_tasks do
118
+ load "path/to/my_railtie.tasks"
119
+ end
120
+ end
121
+ </pre>
122
+
123
+ By default, Rails load generators from your load path. However, if you want to place your generators at a different location, you can specify in your Railtie a block which will load them during normal generators lookup:
124
+
125
+ <pre>
126
+ class MyRailtie < Railtie
127
+ generators do
128
+ require "path/to/my_railtie_generator"
129
+ end
130
+ end
131
+ </pre>
132
+
133
+ Application, Plugin and Engine
134
+
135
+ A Rails::Engine is nothing more than a Railtie with some initializers already set. And since Rails::Application and Rails::Plugin are engines, the same configuration described here can be used in all three.
136
+
137
+ Be sure to look at the documentation of those specific classes for more information.
138
+
139
+ Methods:
140
+
141
+ * abstract_railtie?
142
+ * console
143
+ * eager_load!
144
+ * generators
145
+ * inherited
146
+ * load_console
147
+ * load_generators
148
+ * load_tasks
149
+ * log_subscriber
150
+ * railtie_name
151
+ * rake_tasks
152
+ * subclasses
153
+
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Kristian Mandrup
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-21 00:00:00 +02:00
17
+ date: 2010-08-22 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -82,17 +82,20 @@ files:
82
82
  - README.markdown
83
83
  - Rakefile
84
84
  - VERSION
85
+ - config/database.yml
85
86
  - lib/plugin_toolbox/extender.rb
86
87
  - lib/plugin_toolbox/loader.rb
87
88
  - lib/plugin_toolbox/util.rb
88
- - lib/plugin_toolbox/validator/hook_validator.rb
89
- - lib/plugin_toolbox/validator/type_validator.rb
90
89
  - lib/rails3_plugin_toolbox.rb
90
+ - log/development.log
91
91
  - rails3_plugin_toolbox.gemspec
92
+ - spec/plugin_toolbox/extender_action_spec.rb
93
+ - spec/plugin_toolbox/extender_i18n_spec.rb
92
94
  - spec/plugin_toolbox/extender_spec.rb
93
- - spec/plugin_toolbox/loader_spec.rb
94
- - spec/plugin_toolbox/util_spec.rb
95
95
  - spec/spec_helper.rb
96
+ - wiki/add_rake_tasks.markdown
97
+ - wiki/engine.markdown
98
+ - wiki/how_to_guide.markdown
96
99
  has_rdoc: true
97
100
  homepage: http://github.com/kristianmandrup/rails3_plugin_toolbox
98
101
  licenses: []
@@ -126,7 +129,7 @@ signing_key:
126
129
  specification_version: 3
127
130
  summary: Toolbox to facilitate Rails 3 plugin development
128
131
  test_files:
132
+ - spec/plugin_toolbox/extender_action_spec.rb
133
+ - spec/plugin_toolbox/extender_i18n_spec.rb
129
134
  - spec/plugin_toolbox/extender_spec.rb
130
- - spec/plugin_toolbox/loader_spec.rb
131
- - spec/plugin_toolbox/util_spec.rb
132
135
  - spec/spec_helper.rb
@@ -1,11 +0,0 @@
1
- module Rails::PluginToolbox
2
- module HookValidator
3
- def valid_before_hook?
4
- [:initialize, :configuration, :eager_load].include?(type)
5
- end
6
-
7
- def valid_after_hook?
8
- [:initialize, :i18n, :active_record, :action_view, :action_controller, :action_mailer].include?(type)
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- module Rails::PluginToolbox
2
- module TypeValidator
3
- def valid_type?
4
- [:i18n, :active_record].include?(type)
5
- end
6
-
7
- def action_type? type
8
- [:controller, :view, :mailer].include?(type)
9
- end
10
- end
11
- end
File without changes