Class: Rails::Engine
- Defined in:
- lib/rails/engine.rb,
lib/rails/engine/configurable.rb,
lib/rails/engine/configuration.rb
Overview
Rails::Engine allows you to wrap a specific Rails application and share it accross different applications. Since Rails 3.0, every Rails::Application is nothing more than an Engine, allowing you to share it very easily.
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.
Creating an Engine
In Rails versions before to 3.0, your gems automatically behaved as Engine, however this coupled Rails to Rubygems. Since Rails 3.0, if you want a gem to automatically behave as Engine, you have to specify an Engine for it somewhere inside your plugin lib folder (similar with how we spceify a Railtie):
# lib/my_engine.rb
module MyEngine
class Engine < Rails::Engine
end
end
Then ensure that this file is loaded at the top of your config/application.rb (or in your Gemfile) and it will automatically load models, controllers and helpers inside app, load routes at “config/routes.rb”, load locales at “config/locales/*”, load tasks at “lib/tasks/*”.
Configuration
Besides the Railtie configuration which is shared across the application, in a Rails::Engine you can access autoload_paths, eager_load_paths and autoload_once_paths, which differently from a Railtie, are scoped to the current Engine.
Example:
class MyEngine < Rails::Engine
# Add a load path for this specific Engine
config.autoload_paths << File.("../lib/some/path", __FILE__)
initializer "my_engine.add_middleware" do |app|
app.middleware.use MyEngine::Middleware
end
end
Paths
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.
For example, let’s suppose you want to lay your controllers at lib/controllers, all you need to do is:
class MyEngine < Rails::Engine
paths.app.controllers = "lib/controllers"
end
You can also have your controllers being loaded from both “app/controllers” and “lib/controllers”:
class MyEngine < Rails::Engine
paths.app.controllers << "lib/controllers"
end
The available paths in an Engine are:
class MyEngine < Rails::Engine
paths.app = "app"
paths.app.controllers = "app/controllers"
paths.app.helpers = "app/helpers"
paths.app.models = "app/models"
paths.app.views = "app/views"
paths.lib = "lib"
paths.lib.tasks = "lib/tasks"
paths.config = "config"
paths.config.initializers = "config/initializers"
paths.config.locales = "config/locales"
paths.config.routes = "config/routes.rb"
end
Your Application class adds a couple more paths to this set. And as in your Application, all folders under “app” are automatically added to the load path. So if you have “app/observers”, it’s added by default.
Direct Known Subclasses
Defined Under Namespace
Modules: Configurable Classes: Configuration
Constant Summary
Constants inherited from Railtie
Class Attribute Summary collapse
-
.called_from ⇒ Object
Returns the value of attribute called_from.
Class Method Summary collapse
Instance Method Summary collapse
Methods inherited from Railtie
abstract_railtie?, console, generators, #load_console, #load_generators, log_subscriber, railtie_name, rake_tasks, subclasses
Methods included from Initializable
included, #initializers, #run_initializers
Class Attribute Details
.called_from ⇒ Object
Returns the value of attribute called_from.
94 95 96 |
# File 'lib/rails/engine.rb', line 94 def called_from @called_from end |
Class Method Details
.find_root_with_flag(flag, default = nil) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rails/engine.rb', line 111 def find_root_with_flag(flag, default=nil) root_path = self.called_from while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/#{flag}") parent = File.dirname(root_path) root_path = parent != root_path && parent end root = File.exist?("#{root_path}/#{flag}") ? root_path : default raise "Could not find root path for #{self}" unless root RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? Pathname.new(root). : Pathname.new(root).realpath end |
.inherited(base) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/rails/engine.rb', line 99 def inherited(base) unless base.abstract_railtie? base.called_from = begin # Remove the line number from backtraces making sure we don't leave anything behind call_stack = caller.map { |p| p.split(':')[0..-2].join(':') } File.dirname(call_stack.detect { |p| p !~ %r[railties[\w\-\.]*/lib/rails|rack[\w\-\.]*/lib/rack] }) end end super end |
Instance Method Details
#eager_load! ⇒ Object
134 135 136 137 138 139 140 141 |
# File 'lib/rails/engine.rb', line 134 def eager_load! config.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/ Dir.glob("#{load_path}/**/*.rb").sort.each do |file| require_dependency file.sub(matcher, '\1') end end end |
#load_tasks ⇒ Object
129 130 131 132 |
# File 'lib/rails/engine.rb', line 129 def load_tasks super config.paths.lib.tasks.to_a.sort.each { |ext| load(ext) } end |