engines
Engines
An engine is a self-contained application packaged to mount inside a host. It carries its own routes, controllers, view paths, and initializers under an isolated namespace, and the host mounts it at a path.
Defining an engine
MVC::Keayl::Engine takes a namespace, the controllers it owns, its routes
block, and the view paths it contributes:
use MVC::Keayl::Engine;
my $blog = MVC::Keayl::Engine.new(
namespace => 'Blog',
controllers => [Blog::PostsController, Blog::CommentsController],
view-paths => ['engines/blog/app/views'],
routes-block => {
get '/posts', to => 'posts#index';
get '/posts/:id', to => 'posts#show';
},
);isolate-namespace can also set the namespace after construction.
Namespace isolation
Within the engine, a route target uses the short controller name. The engine
resolves it inside its namespace, so to => 'posts#index' dispatches to
Blog::PostsController (its controller-path is blog/posts). The full path
works too. The engine's controllers are dispatched only by the engine, never by
the host.
Building the endpoint
endpoint builds a dispatcher for the engine's routes and controllers. It is an
endpoint like any other, so it can be called directly or mounted:
$blog.endpoint.call($request);Mounting in a host
Mount the engine endpoint in the host's routes. Requests below the mount point are rebased and handed to the engine:
my $router = routes {
root to => 'home#index';
mount $blog.endpoint, at => '/blog';
};A request for /blog/posts/5 reaches the engine as /posts/5.
Host overrides
A host route declared before the mount takes precedence, so the host can override an engine route:
routes {
get '/blog/posts', to => 'marketing#featured'; # wins over the engine
mount $blog.endpoint, at => '/blog';
}Unmatched paths still fall through to the engine.
The host can also override an engine's views. Pass view-path-overrides when
building the endpoint, and those paths are searched before the engine's, so a
host template of the same name wins:
$blog.endpoint(view-path-overrides => ['app/views/blog']);view-paths, helper-paths, and asset-paths expose what the engine
contributes, and append-view-paths (and its helper/asset counterparts) add
more.
Initializers
An engine registers initializers and runs them in order, for setup the engine needs at boot:
$blog.initializer('seed-cache', -> $engine { ... });
$blog.run-initializers;