r3_plugin_toolbox 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format nested --color
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Kristian Mandrup
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,158 @@
1
+ # Rails 3 Plugin Toolbox
2
+
3
+ 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
+ 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
+ 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
+
9
+ ## Install
10
+
11
+ <code>gem install r3_plugin_toolbox</code>
12
+
13
+ ## Usage
14
+
15
+ <pre>
16
+ # my_plugin/lib/my_plugin/rails/extensions.rb
17
+
18
+ require 'rails/all'
19
+ require 'r3_plugin_toolbox'
20
+
21
+ Rails3::PluginExtender.new do
22
+ extend_from_module Ultra::View, :stuff, :in => :view
23
+ extend_with Ultra::Controller, :in => :controller
24
+
25
+ before :initialize do
26
+ "Rails not yet initialized!"
27
+ end
28
+
29
+ extend_rails :i18n do
30
+ with MyAddition
31
+ extend_from_module Ultra::Power, :util, :logging, :monitor
32
+
33
+ before :initialize do
34
+ MyOtherAddition.say 'before localized!'
35
+ end
36
+
37
+ before :configuration do
38
+ MyOtherAddition.configured = 'was configured!'
39
+ end
40
+
41
+ before :eager_load do
42
+ puts "before eager load!"
43
+ end
44
+
45
+ after :initialize do
46
+ MyAddition.say 'localized!'
47
+ end
48
+ end
49
+ end
50
+ </pre>
51
+
52
+ More API examples
53
+
54
+ <pre>
55
+ Rails3::PluginExtender.new do
56
+ extend_rails :view do # or use :action_view
57
+ with MyViewAddition
58
+ end
59
+
60
+ extend_rails :controller do # or use :action_mailer
61
+ with MyViewAddition
62
+ end
63
+
64
+ extend_rails :mailer do # or use :action_mailer
65
+ with MyMailAddition, 'MyOtherMailAddition'
66
+ end
67
+
68
+ extend_rails :AR do # active record
69
+ with MyActiveRecordAddition
70
+ end
71
+
72
+ extend_rails :active_record do
73
+ with MyExtraScopeHelpers
74
+ end
75
+
76
+ extend_rails(:controller) do
77
+ extend_from_module Ultra::Power, :util, :logging, :monitor
78
+ extend_from_module Ultra::Power::More, :extra, :stuff
79
+ end
80
+
81
+ after(:initialize) do
82
+ puts "Rails initialized!"
83
+ end
84
+ end
85
+ </pre>
86
+
87
+ ## RSpec 2 matchers
88
+
89
+ The library comes with a special Matcher to facilitate making Rails 3 extension specs
90
+
91
+ * be_extended_with module_name, *submodules
92
+
93
+ _Usage example:_
94
+
95
+ <pre>
96
+
97
+ require 'rspec'
98
+ require 'r3_plugin_toolbox'
99
+ require 'rails/all'
100
+
101
+ describe "My Plugin rails extensions" do
102
+ it "should extend Action View with View Helpers" do
103
+ Rails3::PluginExtender.new do
104
+ extend_rails :view do
105
+ extend_from_module Helper::View, :panel, :window
106
+ extend_with Helper::View::Button, Helper::View::Form
107
+ end
108
+ end
109
+
110
+ after_init :view do
111
+ :view.should be_extended_with Helper::View, :panel, :window, :button, :form
112
+ :view.should_not be_extended_with Helper::View, :unknown
113
+ end
114
+
115
+ after_init :controller do
116
+ :controller.should be_extended_with Helper::Controller, :stuff
117
+ :controller.should_not be_extended_with My::Paginator
118
+ end
119
+
120
+ # first arg is the App name, the remaining symbols are
121
+ # the identifiers for which railties to initialize
122
+ init_app_railties :minimal, :view, :controller
123
+ end
124
+ end
125
+
126
+ # alternative RSpec configuration using macros
127
+
128
+ describe "My other Plugin rails extensions" do
129
+ before :each do
130
+ Rails3::PluginExtender.new do
131
+ extend_rails :view do
132
+ extend_from_module Helper::View, :grid, :tree
133
+ end
134
+ end
135
+ end
136
+
137
+ after_init :view do
138
+ :view.should be_extended_with Helper::View, :panel, :window, :button, :form
139
+ end
140
+
141
+ it "should extend Action View" do
142
+ init_app_railties :minimal, :view
143
+ end
144
+ </pre>
145
+
146
+ ## Note on Patches/Pull Requests
147
+
148
+ * Fork the project.
149
+ * Make your feature addition or bug fix.
150
+ * Add tests for it. This is important so I don't break it in a
151
+ future version unintentionally.
152
+ * Commit, do not mess with rakefile, version, or history.
153
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
154
+ * Send me a pull request. Bonus points for topic branches.
155
+
156
+ ## Copyright
157
+
158
+ Copyright (c) 2010 Kristian Mandrup. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "r3_plugin_toolbox"
5
+ gem.summary = %Q{Toolbox to facilitate Rails 3 plugin development}
6
+ gem.description = %Q{Provides a more intuitive DSL for Rails 3 plugin configuration and a specialized RSpec 2 matcher. Makes it much easier to develop Rails 3 plugins!}
7
+ gem.email = "kmandrup@gmail.com"
8
+ gem.homepage = "http://github.com/kristianmandrup/rails3_plugin_toolbox"
9
+ gem.authors = ["Kristian Mandrup"]
10
+ gem.add_development_dependency "rspec", "~> 2.0.0"
11
+
12
+ gem.add_dependency "rails", "~> 3.0.0"
13
+ gem.add_dependency "require_all", "~> 1.1.0"
14
+
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.5
@@ -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
@@ -0,0 +1,65 @@
1
+ require 'plugin_toolbox/util'
2
+
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
+ end
12
+
13
+ # load after: [:initialize, :configuration, :eager_load]
14
+ def extend_rails(type, &block)
15
+ on_load(type, &block)
16
+ end
17
+
18
+
19
+ # convenience method to extend with multiple modules all within the same base module
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
22
+ module_names.each do |name|
23
+ extend_with get_constant(base_name, name), 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
33
+ end
34
+ end
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 get_constant(base_name, name)
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
+
53
+ protected
54
+
55
+ def extend! module_name, type
56
+ do_extend! get_module(module_name), get_load_type(type.to_sym)
57
+ end
58
+
59
+ def do_extend! module_name, type
60
+ ActiveSupport.on_load(type) do
61
+ include module_name
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,32 @@
1
+ module Rails3
2
+ class PluginExtender
3
+ module LoadHandler
4
+ include Rails3::PluginExtender::Util
5
+
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
10
+ end
11
+
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
16
+ end
17
+
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
22
+ 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
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ require 'rspec'
2
+
3
+ RSpec.configure do |config|
4
+ config.include Rails3::PluginExtender::Matchers
5
+ config.extend Rails3::PluginExtender::Macro
6
+ end
7
+
8
+ module RSpec::Core
9
+ class ExampleGroup
10
+ include Rails3::PluginExtender::Macro
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ module Rails3
2
+ class PluginExtender
3
+ module Macro
4
+ class << self
5
+ include Rails3::PluginExtender::Util
6
+ end
7
+
8
+ MACRO = Rails3::PluginExtender::Macro
9
+
10
+ def after_init component, &block
11
+ type = MACRO.get_load_type component
12
+ Rails3::PluginExtender.new do
13
+ extend_rails type do
14
+ after :initialize do
15
+ yield self
16
+ end
17
+ end
18
+ end
19
+ end # def
20
+
21
+ def init_app_railties app_name, *railties
22
+ app = "#{app_name.to_s.camelize}::Application".constantize
23
+ app.initialize!
24
+ railties.each do |railtie|
25
+ MACRO.get_base_class(railtie).constantize
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,64 @@
1
+ module Rails3
2
+ class PluginExtender
3
+ module Matchers
4
+ class BeExtendedWith
5
+ include Rails3::PluginExtender::Util
6
+
7
+ attr_reader :methods, :module_const, :rails_const, :submodules, :cause, :rails_const_name, :bad_const
8
+
9
+ def initialize(module_const, submodules=nil)
10
+ @module_const = module_const
11
+ raise ArgumentError, "List of submodules must be given as a collection of Symbols or Strings" if submodules && !submodules.respond_to?(:flatten)
12
+ @submodules = submodules.flatten if submodules
13
+ end
14
+
15
+ def matches? type
16
+ begin
17
+ @rails_const_name = get_base_class(type)
18
+ @bad_const = module_const
19
+ @rails_const = rails_const_name.constantize
20
+
21
+ return match_submodules? if submodules
22
+
23
+ methods_included? module_const.instance_methods
24
+ rescue
25
+ @cause = ", but the extension module wasn't found"
26
+ false
27
+ end
28
+ end
29
+
30
+ def base_class_methods
31
+ (rails_const == I18n) ? rails_const.methods : rails_const.instance_methods
32
+ end
33
+
34
+ def match_submodules?
35
+ submodules.each do |name|
36
+ @bad_const = make_constant(module_const, name)
37
+ return false if !methods_included? get_methods(name)
38
+ end
39
+ true
40
+ end
41
+
42
+ def methods_included? methods
43
+ (base_class_methods & methods) == methods
44
+ end
45
+
46
+ def get_methods name
47
+ get_constant(module_const, name).instance_methods
48
+ end
49
+
50
+ def failure_message
51
+ "Expected the rails class #{rails_const_name} to be extended with the methods in #{bad_const}#{cause}"
52
+ end
53
+
54
+ def negative_failure_message
55
+ "Did not expect the rails class #{rails_const_name} to be extended with the methods in #{bad_const}"
56
+ end
57
+ end
58
+
59
+ def be_extended_with(module_const, *submodules)
60
+ BeExtendedWith.new module_const, submodules
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,62 @@
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_base_class type
8
+ type = get_load_type(type).to_s
9
+ const = act_type?(type) ? rails_const_base(type) : "#{type.to_s.camelize}"
10
+ end
11
+
12
+ def act_type? type
13
+ type =~/action/ || type =~/active/
14
+ end
15
+
16
+ def get_constant base_name, name
17
+ make_constant(base_name, name).constantize
18
+ end
19
+
20
+ def rails_const_base type
21
+ "#{type.to_s.camelize}::Base"
22
+ end
23
+
24
+ def make_constant base_name, name
25
+ "#{base_name.to_s.camelize}::#{name.to_s.camelize}"
26
+ end
27
+
28
+ def get_load_type type
29
+ return ACTIVE_MODULES[type] if ACTIVE_MODULES[type]
30
+ return type if ACTIVE_MODULES.values.include? type
31
+ return type if type == :i18n
32
+ logger.warn "WARNING: The Rails 3 load handler for the component #{type} is not part of the default load process."
33
+ end
34
+
35
+ def get_module module_name
36
+ case module_name
37
+ when Constant
38
+ module_name
39
+ when String
40
+ module_name.to_s.constantize
41
+ else
42
+ raise ArgumentError, "#{module_name} could not be converted into a module constant"
43
+ end
44
+ end
45
+
46
+ protected
47
+
48
+ def valid_before_hook? type
49
+ [INIT, :configuration, :eager_load].include?(type)
50
+ end
51
+
52
+ def valid_after_hook? type
53
+ INIT == type
54
+ end
55
+
56
+ def valid_load_hook? type
57
+ @valid_load_hooks ||= [ACTIVE_MODULES.keys, ACTIVE_MODULES.values, :i18n].flatten
58
+ @valid_load_hooks.include?(type)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,7 @@
1
+ module Rails3
2
+ end
3
+
4
+ require 'active_support/inflector'
5
+ require 'require_all'
6
+
7
+ require_all File.dirname(__FILE__) + '/plugin_toolbox'
File without changes
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{r3_plugin_toolbox}
8
+ s.version = "0.3.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kristian Mandrup"]
12
+ s.date = %q{2010-09-13}
13
+ s.description = %q{Provides a more intuitive DSL for Rails 3 plugin configuration and a specialized RSpec 2 matcher. Makes it much easier to develop Rails 3 plugins!}
14
+ s.email = %q{kmandrup@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ ".rspec",
23
+ "LICENSE",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "config/database.yml",
28
+ "lib/plugin_toolbox/extender.rb",
29
+ "lib/plugin_toolbox/loader.rb",
30
+ "lib/plugin_toolbox/rspec/config.rb",
31
+ "lib/plugin_toolbox/rspec/macro.rb",
32
+ "lib/plugin_toolbox/rspec/matchers/be_extended_with.rb",
33
+ "lib/plugin_toolbox/util.rb",
34
+ "lib/r3_plugin_toolbox.rb",
35
+ "log/development.log",
36
+ "r3_plugin_toolbox.gemspec",
37
+ "rails3_plugin_toolbox.gemspec",
38
+ "spec/plugin_toolbox/extend_view_content_spec.rb",
39
+ "spec/plugin_toolbox/extender_action_spec.rb",
40
+ "spec/plugin_toolbox/extender_i18n_spec.rb",
41
+ "spec/plugin_toolbox/extender_spec.rb",
42
+ "spec/spec_helper.rb",
43
+ "wiki/add_rake_tasks.markdown",
44
+ "wiki/engine.markdown",
45
+ "wiki/how_to_guide.markdown"
46
+ ]
47
+ s.homepage = %q{http://github.com/kristianmandrup/rails3_plugin_toolbox}
48
+ s.rdoc_options = ["--charset=UTF-8"]
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = %q{1.3.7}
51
+ s.summary = %q{Toolbox to facilitate Rails 3 plugin development}
52
+ s.test_files = [
53
+ "spec/plugin_toolbox/extend_view_content_spec.rb",
54
+ "spec/plugin_toolbox/extender_action_spec.rb",
55
+ "spec/plugin_toolbox/extender_i18n_spec.rb",
56
+ "spec/plugin_toolbox/extender_spec.rb",
57
+ "spec/spec_helper.rb"
58
+ ]
59
+
60
+ if s.respond_to? :specification_version then
61
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
+ s.add_development_dependency(%q<rspec>, ["~> 2.0.0"])
66
+ s.add_runtime_dependency(%q<rails>, ["~> 3.0.0"])
67
+ s.add_runtime_dependency(%q<require_all>, ["~> 1.1.0"])
68
+ else
69
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
70
+ s.add_dependency(%q<rails>, ["~> 3.0.0"])
71
+ s.add_dependency(%q<require_all>, ["~> 1.1.0"])
72
+ end
73
+ else
74
+ s.add_dependency(%q<rspec>, ["~> 2.0.0"])
75
+ s.add_dependency(%q<rails>, ["~> 3.0.0"])
76
+ s.add_dependency(%q<require_all>, ["~> 1.1.0"])
77
+ end
78
+ end
79
+
@@ -0,0 +1,78 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rails3_plugin_toolbox}
8
+ s.version = "0.3.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kristian Mandrup"]
12
+ s.date = %q{2010-09-13}
13
+ s.description = %q{Provides a more intuitive DSL for Rails 3 plugin configuration and a specialized RSpec 2 matcher. Makes it much easier to develop Rails 3 plugins!}
14
+ s.email = %q{kmandrup@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ ".rspec",
23
+ "LICENSE",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "config/database.yml",
28
+ "lib/plugin_toolbox/extender.rb",
29
+ "lib/plugin_toolbox/loader.rb",
30
+ "lib/plugin_toolbox/rspec/config.rb",
31
+ "lib/plugin_toolbox/rspec/macro.rb",
32
+ "lib/plugin_toolbox/rspec/matchers/be_extended_with.rb",
33
+ "lib/plugin_toolbox/util.rb",
34
+ "lib/rails3_plugin_toolbox.rb",
35
+ "log/development.log",
36
+ "rails3_plugin_toolbox.gemspec",
37
+ "spec/plugin_toolbox/extend_view_content_spec.rb",
38
+ "spec/plugin_toolbox/extender_action_spec.rb",
39
+ "spec/plugin_toolbox/extender_i18n_spec.rb",
40
+ "spec/plugin_toolbox/extender_spec.rb",
41
+ "spec/spec_helper.rb",
42
+ "wiki/add_rake_tasks.markdown",
43
+ "wiki/engine.markdown",
44
+ "wiki/how_to_guide.markdown"
45
+ ]
46
+ s.homepage = %q{http://github.com/kristianmandrup/rails3_plugin_toolbox}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.7}
50
+ s.summary = %q{Toolbox to facilitate Rails 3 plugin development}
51
+ s.test_files = [
52
+ "spec/plugin_toolbox/extend_view_content_spec.rb",
53
+ "spec/plugin_toolbox/extender_action_spec.rb",
54
+ "spec/plugin_toolbox/extender_i18n_spec.rb",
55
+ "spec/plugin_toolbox/extender_spec.rb",
56
+ "spec/spec_helper.rb"
57
+ ]
58
+
59
+ if s.respond_to? :specification_version then
60
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
61
+ s.specification_version = 3
62
+
63
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
64
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
65
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0.rc"])
66
+ s.add_runtime_dependency(%q<require_all>, [">= 1.1.0"])
67
+ else
68
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
69
+ s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
70
+ s.add_dependency(%q<require_all>, [">= 1.1.0"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
74
+ s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
75
+ s.add_dependency(%q<require_all>, [">= 1.1.0"])
76
+ end
77
+ end
78
+
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ module Helper
4
+ module View
5
+ module Panel
6
+ def draw_panel
7
+ 'panel'
8
+ end
9
+ end
10
+
11
+ module Window
12
+ def draw_window
13
+ 'panel'
14
+ end
15
+ end
16
+
17
+ module Button
18
+ def draw_button
19
+ 'button'
20
+ end
21
+ end
22
+
23
+ module Form
24
+ def draw_form
25
+ 'form'
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ describe Rails3::PluginExtender do
32
+ describe '#extend_rails' do
33
+
34
+ before :each do
35
+ Rails3::PluginExtender.new do
36
+ extend_rails :view do
37
+ extend_from_module Helper::View, :panel, :window
38
+ extend_with Helper::View::Button, Helper::View::Form
39
+ end
40
+ end
41
+ end
42
+
43
+ # after_init :view do |view|
44
+ # view.should be_extended_with Helper::View, :panel, :window, :button, :form
45
+ # end
46
+
47
+
48
+ it "should extend Action View" do
49
+ after_init :view do
50
+ puts "View initialized!"
51
+
52
+ :view.should be_extended_with Helper::View, :panel, :window, :button, :form
53
+ :view.should_not be_extended_with Helper::View, :unknown
54
+ lambda { :view.should be_extended_with Helper::View, :unknown }.should raise_error
55
+
56
+ # :view.should be_extended_with Helper::View, :unknown
57
+ end
58
+
59
+ init_app_railties :minimal, :view
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,62 @@
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
+
8
+ extender.extend_rails :view do
9
+ with MyAddition
10
+
11
+ after :initialize do
12
+ MyAddition.say 'view it!'
13
+ end
14
+ end
15
+
16
+ # Initialize the rails application
17
+ Minimal::Application.initialize!
18
+
19
+ ActionView::Base.instance_methods.grep(/zzz/).should_not be_empty
20
+
21
+ MyAddition.heard.should == 'view it!'
22
+ end
23
+
24
+ it "should extend Action Controller" do
25
+ Rails3::PluginExtender.new do
26
+ extend_rails :controller do
27
+ with MyAddition
28
+
29
+ after :initialize do
30
+ MyAddition.say 'control it!'
31
+ end
32
+ end
33
+ end
34
+
35
+ # Initialize the rails application
36
+ Minimal::Application.initialize!
37
+
38
+ ActionController::Base.instance_methods.grep(/zzz/).should_not be_empty
39
+
40
+ MyAddition.heard.should == 'control it!'
41
+ end
42
+
43
+ it "should extend Action Mailer" do
44
+ Rails3::PluginExtender.new do
45
+ extend_rails :mailer do
46
+ with MyAddition
47
+
48
+ after :initialize do
49
+ MyAddition.say 'mail me!'
50
+ end
51
+ end
52
+ end
53
+
54
+ # Initialize the rails application
55
+ Minimal::Application.initialize!
56
+
57
+ ActionMailer::Base.instance_methods.grep(/zzz/).should_not be_empty
58
+
59
+ MyAddition.heard.should == 'mail me!'
60
+ end
61
+ end
62
+ 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,37 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+
4
+ def extend_unknown
5
+ Rails3::PluginExtender.new do
6
+ extend_rails :unknown do
7
+ with MyAddition
8
+ end
9
+ end
10
+ end
11
+
12
+ describe Rails3::PluginExtender do
13
+ describe '#extend_rails' do
14
+ it "should NOT extend Unknown" do
15
+ lambda { extend_unknown }.should raise_error
16
+ end
17
+
18
+ it "should extend Active Record" do
19
+ Rails3::PluginExtender.new do
20
+ extend_rails :AR do
21
+ with MyAddition
22
+
23
+ after :initialize do
24
+ MyAddition.say 'record me!'
25
+ end
26
+ end
27
+ end
28
+
29
+ # Initialize the rails application
30
+ Minimal::Application.initialize!
31
+
32
+ ActiveRecord::Base.instance_methods.grep(/zzz/).should_not be_empty
33
+
34
+ MyAddition.heard.should == 'record me!'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ require 'rspec'
2
+ require 'rspec/autorun'
3
+ require 'r3_plugin_toolbox'
4
+
5
+ # See http://www.igvita.com/2010/08/04/rails-3-internals-railtie-creating-plugins/
6
+
7
+
8
+ # require 'active_record'
9
+ # require 'action_mailer'
10
+ # require 'active_support'
11
+ require 'action_controller'
12
+ require 'action_view'
13
+ require 'active_support/railtie'
14
+ # require 'rails/all'
15
+
16
+ module Minimal
17
+ class Application < Rails::Application
18
+ config.active_support.deprecation = :log
19
+ end
20
+ end
21
+
22
+ module MyAddition
23
+ def zzz
24
+ 'zzz'
25
+ end
26
+
27
+ class << self
28
+ attr_accessor :heard
29
+
30
+ def say message
31
+ @heard = message
32
+ end
33
+ end
34
+ end
35
+
36
+ module MyOtherAddition
37
+ def yyy
38
+ 'yyy'
39
+ end
40
+
41
+ class << self
42
+ attr_accessor :heard
43
+ attr_accessor :configured
44
+
45
+ def say message
46
+ @heard = message
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+ RSpec.configure do |config|
53
+ 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 ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: r3_plugin_toolbox
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 5
9
+ version: 0.3.5
10
+ platform: ruby
11
+ authors:
12
+ - Kristian Mandrup
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-13 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 0
31
+ - 0
32
+ version: 2.0.0
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rails
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 3
45
+ - 0
46
+ - 0
47
+ version: 3.0.0
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: require_all
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 1
60
+ - 1
61
+ - 0
62
+ version: 1.1.0
63
+ type: :runtime
64
+ version_requirements: *id003
65
+ description: Provides a more intuitive DSL for Rails 3 plugin configuration and a specialized RSpec 2 matcher. Makes it much easier to develop Rails 3 plugins!
66
+ email: kmandrup@gmail.com
67
+ executables: []
68
+
69
+ extensions: []
70
+
71
+ extra_rdoc_files:
72
+ - LICENSE
73
+ - README.markdown
74
+ files:
75
+ - .document
76
+ - .gitignore
77
+ - .rspec
78
+ - LICENSE
79
+ - README.markdown
80
+ - Rakefile
81
+ - VERSION
82
+ - config/database.yml
83
+ - lib/plugin_toolbox/extender.rb
84
+ - lib/plugin_toolbox/loader.rb
85
+ - lib/plugin_toolbox/rspec/config.rb
86
+ - lib/plugin_toolbox/rspec/macro.rb
87
+ - lib/plugin_toolbox/rspec/matchers/be_extended_with.rb
88
+ - lib/plugin_toolbox/util.rb
89
+ - lib/r3_plugin_toolbox.rb
90
+ - log/development.log
91
+ - r3_plugin_toolbox.gemspec
92
+ - rails3_plugin_toolbox.gemspec
93
+ - spec/plugin_toolbox/extend_view_content_spec.rb
94
+ - spec/plugin_toolbox/extender_action_spec.rb
95
+ - spec/plugin_toolbox/extender_i18n_spec.rb
96
+ - spec/plugin_toolbox/extender_spec.rb
97
+ - spec/spec_helper.rb
98
+ - wiki/add_rake_tasks.markdown
99
+ - wiki/engine.markdown
100
+ - wiki/how_to_guide.markdown
101
+ has_rdoc: true
102
+ homepage: http://github.com/kristianmandrup/rails3_plugin_toolbox
103
+ licenses: []
104
+
105
+ post_install_message:
106
+ rdoc_options:
107
+ - --charset=UTF-8
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ requirements: []
127
+
128
+ rubyforge_project:
129
+ rubygems_version: 1.3.7
130
+ signing_key:
131
+ specification_version: 3
132
+ summary: Toolbox to facilitate Rails 3 plugin development
133
+ test_files:
134
+ - spec/plugin_toolbox/extend_view_content_spec.rb
135
+ - spec/plugin_toolbox/extender_action_spec.rb
136
+ - spec/plugin_toolbox/extender_i18n_spec.rb
137
+ - spec/plugin_toolbox/extender_spec.rb
138
+ - spec/spec_helper.rb