Permalink
Browse files

Merge branch 'release/1.3000_02'

  • Loading branch information...
2 parents 6552dd3 + a2291c4 commit 9455e2d51a157ff09ec331597f58061f1ad141c8 Alexis Sukrieh committed Jan 3, 2011
View
@@ -1 +1 @@
-90.9
+92.4
View
17 CHANGES
@@ -1,3 +1,20 @@
+Dancer 1.3000_02
+
+ [ Sawyer X ]
+ * Added forward() functionality (incl. tests and docs)
+
+ [ Damien Krotkine ]
+ * FIX for --no-check switch in script/dancer
+ * Refactoring of Dancer::Template::Abstract
+ - add support of apply_layout and apply_renderer
+ - deprecation of render_with_layout (now handled better)
+ - add an accessor "engine" to the DSL to access any engine singleton
+ - better interface for Dancer::Object and Dancer::Object::Singleton
+ - updated tests accordingly
+
+ [ Jonathan Otsuka ]
+ * Bring dancer application creation pod up-to-date 1.2003
+
Dancer 1.3000_01
[ Damien Krotkine ]
View
@@ -148,6 +148,7 @@ t/03_route_handler/24_named_captures.t
t/03_route_handler/26_after_hook.t
t/03_route_handler/27_issue_77_pass_breaks_routes.t
t/03_route_handler/28_plack_mount.t
+t/03_route_handler/29_forward.t
t/03_route_handler/29_redirect_immediately.t
t/03_route_handler/30_bug_gh190.t
t/03_route_handler/public/404.html
@@ -183,6 +184,7 @@ t/07_apphandlers/04_standalone_app.t
t/07_apphandlers/05_middlewares.t
t/07_apphandlers/05_psgi_api.t
t/07_apphandlers/06_debug.t
+t/07_apphandlers/07_middleware_map.t
t/08_session/000_create_fake_env.t
t/08_session/01_load.t
t/08_session/02_dependency_check.t
View
@@ -31,7 +31,7 @@ use File::Basename 'basename';
use base 'Exporter';
$AUTHORITY = 'SUKRIA';
-$VERSION = '1.3000_01';
+$VERSION = '1.3000_02';
@EXPORT = qw(
after
any
@@ -45,7 +45,9 @@ $VERSION = '1.3000_01';
del
dirname
error
+ engine
false
+ forward
from_dumper
from_json
from_yaml
@@ -107,9 +109,11 @@ sub content_type { Dancer::Response->content_type(@_) }
sub dance { Dancer::start(@_) }
sub debug { goto &Dancer::Logger::debug }
sub dirname { Dancer::FileUtils::dirname(@_) }
+sub engine { Dancer::Engine->engine(@_) }
sub error { goto &Dancer::Logger::error }
sub send_error { Dancer::Helpers->error(@_) }
sub false {0}
+sub forward { Dancer::Response->forward(shift) }
sub from_dumper { Dancer::Serializer::Dumper::from_dumper(@_) }
sub from_json { Dancer::Serializer::JSON::from_json(@_) }
sub from_yaml { Dancer::Serializer::YAML::from_yaml(@_) }
@@ -445,6 +449,14 @@ Returns the dirname of the path given:
my $dir = dirname($some_path);
+=head2 engine
+
+Given an namespace, returns the current engine object
+
+ my $template_engine = engine 'template';
+ my $html = $template_engine->apply_renderer(...);
+ $template_engine->apply_layout($html);
+
=head2 error
Logs a message of error level:
@@ -455,6 +467,35 @@ Logs a message of error level:
Constant that returns a false value (0).
+=head2 forward
+
+Runs an internal redirect of the current request to another request. This helps
+you avoid having to redirect the user using HTTP and set another request to your
+application.
+
+It effectively lets you chain routes together in a clean manner.
+
+ get qr{ /demo/articles/(.+) }x => sub {
+ my ($article_id) = splat;
+
+ # you'll have to implement this next sub yourself :)
+ change_the_main_database_to_demo();
+
+ forward '/articles/$article_id';
+ };
+
+In the above example, the users that reach I</demo/articles/30> will actually
+reach I</articles/30> but we've changed the database to demo before.
+
+This is pretty cool because it lets us retain our paths and offer a demo
+database by merely going to I</demo/...>.
+
+You'll notice that in the example we didn't indicate whether it was B<GET> or
+B<POST>. That is because C<forward> chains the same type of route the user
+reached. If it was a B<GET>, it will remain a B<GET>.
+
+Broader functionality might be added in the future.
+
=head2 from_dumper ($structure)
Deserializes a Data::Dumper structure.
@@ -682,13 +723,19 @@ function, e.g.
Allows a handler to provide plain HTML (or other content), but have it rendered
within the layout still.
-For example:
+This method is B<DEPRECATED>, and will be removed soon. Instead, you should be
+using the C<engine> keyword:
get '/foo' => sub {
# Do something which generates HTML directly (maybe using
# HTML::Table::FromDatabase or something)
my $content = ...;
- render_with_layout $content;
+
+ # get the template engine
+ my $template_engine = engine 'template';
+
+ # apply the layout (not the renderer), and return the result
+ $template_engine->apply_layout($content)
};
It works very similarly to C<template> in that you can pass tokens to be used in
View
@@ -33,16 +33,15 @@ sub build {
croak "cannot build engine without type and name "
unless $name and $type;
- my $class_name = ucfirst($type);
- my $namespace = "Dancer::${class_name}";
+ my $class_name = $class->_engine_class($type);
$config ||= {};
$config->{engines} ||= {};
my $settings = $config->{engines}{$name} || {};
# trying to load the engine
my $engine_class =
- Dancer::ModuleLoader->class_from_setting($namespace => $name);
+ Dancer::ModuleLoader->class_from_setting($class_name => $name);
croak "unknown $type engine '$name', "
. "perhaps you need to install $engine_class?"
@@ -56,6 +55,18 @@ sub build {
);
}
+sub _engine_class {
+ my ($class, $type) = @_;
+ $type = ucfirst($type);
+ return "Dancer::${type}";
+}
+
+sub engine {
+ my ($class, $type) = @_;
+ return $class->_engine_class($type)->engine();
+}
+
+
1;
__END__
View
@@ -26,13 +26,38 @@ sub start {
my $self = shift;
my $app = $self->psgi_app();
- if (Dancer::Config::setting('plack_middlewares')) {
- $app = $self->apply_plack_middlewares($app);
+ foreach my $setting (qw/plack_middlewares plack_middlewares_map/) {
+ if (Dancer::Config::setting($setting)) {
+ my $method = 'apply_'.$setting;
+ $app = $self->$method($app);
+ }
}
return $app;
}
+sub apply_plack_middlewares_map {
+ my ($self, $app) = @_;
+
+ my $mw_map = Dancer::Config::setting('plack_middlewares_map');
+
+ foreach my $req (qw(Plack::App::URLMap Plack::Builder)) {
+ croak "$req is needed to use apply_plack_middlewares_map"
+ unless Dancer::ModuleLoader->load($req);
+ }
+
+ my $urlmap = Plack::App::URLMap->new;
+
+ while ( my ( $path, $mw ) = each %$mw_map ) {
+ my $builder = Plack::Builder->new();
+ map { $builder->add_middleware(@$_) } @$mw;
+ $urlmap->map( $path => $builder->to_app($app) );
+ }
+
+ $urlmap->map('/' => $app) unless $mw_map->{'/'};
+ return $urlmap->to_app;
+}
+
sub apply_plack_middlewares {
my ($self, $app) = @_;
@@ -44,13 +69,12 @@ sub apply_plack_middlewares {
my $builder = Plack::Builder->new();
# XXX remove this after 1.2
- if (ref $middlewares eq 'HASH') {
- carp 'Listing Plack middlewares as a hash ref is DEPRECATED. ' .
- 'Must be listed as an array ref.';
+ if ( ref $middlewares eq 'HASH' ) {
+ carp 'Listing Plack middlewares as a hash ref is DEPRECATED. '
+ . 'Must be listed as an array ref.';
- for my $m (keys %$middlewares) {
- $builder->add_middleware($m, @{$middlewares->{$m}});
- }
+ map { $builder->add_middleware( $_, @{ $middlewares->{$_} } ) }
+ keys %$middlewares;
}
else {
map {
View
@@ -6,6 +6,7 @@ package Dancer::Helpers;
use strict;
use warnings;
+use Carp qw(carp);
use Dancer::Response;
use Dancer::Config 'setting';
@@ -32,70 +33,49 @@ sub send_file {
sub template {
my ($view, $tokens, $options) = @_;
- my $app = Dancer::App->current;
-
- # If 'layout' was given in the options hashref, use it if it's a true value,
- # or don't use a layout if it was false (0, or undef); if layout wasn't
- # given in the options hashref, go with whatever the current layout setting
- # is.
- my $layout =
- exists $options->{layout}
- ? ($options->{layout} ? $options->{layout} : undef)
- : $app->setting('layout');
-
-
- # these are the default tokens provided for template processing
- $tokens ||= {};
- $tokens->{dancer_version} = $Dancer::VERSION;
- $tokens->{settings} = Dancer::Config->settings;
- $tokens->{request} = Dancer::SharedData->request;
- $tokens->{params} = Dancer::SharedData->request->params;
-
- if (setting('session')) {
- $tokens->{session} = Dancer::Session->get;
- }
-
my $content;
- if ($view) {
- $view = Dancer::Template->engine->view($view);
- if (!-r $view) {
+ if ($view) {
+ $content = Dancer::Template->engine->apply_renderer($view, $tokens);
+ if (! defined $content) {
my $error = Dancer::Error->new(
code => 404,
message => "Page not found",
);
return Dancer::Response->set($error->render);
}
-
- $_->($tokens) for (@{$app->registry->hooks->{before_template}});
-
- $content = Dancer::Template->engine->render($view, $tokens);
- return $content if not defined $layout;
} else {
- # No view name specified; look for an option named content, and,
- # if found, use that as the content, putting the layout around it.
- if (exists $options->{content}) {
- $content = delete $options->{content};
- return $content if not defined $layout;
- } else {
- my $error = Dancer::Error->new(
- code => 404,
- message => "Page not found",
- );
- return Dancer::Response->set($error->render);
- }
+ $options ||= {};
+ $content = delete $options->{content};
}
- my $full_content =
- Dancer::Template->engine->layout($layout, $tokens, $content);
- return $full_content;
+ my $full_content = Dancer::Template->engine->apply_layout($content, $tokens, $options);
+ defined $full_content
+ and return $full_content;
+
+ my $error = Dancer::Error->new(
+ code => 404,
+ message => "Page not found",
+ );
+ return Dancer::Response::set($error->render);
}
+# DEPRECATED
sub render_with_layout {
my ($content, $tokens, $options) = @_;
- $options ||= {};
- $options->{content} = $content;
- return template('', $tokens, $options);
+ carp "'render_with_layout' is DEPRECATED, use the 'engine' keyword "
+ . "to get the template engine, and use 'apply_layout' on the result";
+
+ my $full_content = Dancer::Template->engine->apply_layout($content, $tokens, $options);
+
+ if (! defined $full_content) {
+ my $error = Dancer::Error->new(
+ code => 404,
+ message => "Page not found",
+ );
+ return Dancer::Response::set($error->render);
+ }
+ return $full_content;
}
sub error {
@@ -174,7 +174,7 @@ the request with the next matching route.
This is done with the B<pass> keyword, like in the following example
get '/say/:word' => sub {
- pass if (params->{word} =~ /^\d+$/);
+ return pass if (params->{word} =~ /^\d+$/);
"I say a word: ".params->{word};
};
View
@@ -58,6 +58,21 @@ sub get_attributes {
return \@attributes;
}
+# accessor code for normal objects
+# (overloaded in D::O::Singleton for instance)
+sub _setter_code {
+ my ($class, $attr) = @_;
+ sub {
+ my ($self, $value) = @_;
+ if (@_ == 1) {
+ return $self->{$attr};
+ }
+ else {
+ return $self->{$attr} = $value;
+ }
+ };
+}
+
# accessors builder
sub attributes {
my ($class, @attributes) = @_;
@@ -67,15 +82,7 @@ sub attributes {
# define setters and getters for each attribute
foreach my $attr (@attributes) {
- my $code = sub {
- my ($self, $value) = @_;
- if (@_ == 1) {
- return $self->{$attr};
- }
- else {
- return $self->{$attr} = $value;
- }
- };
+ my $code = $class->_setter_code($attr);
my $method = "${class}::${attr}";
{ no strict 'refs'; *$method = $code; }
}
Oops, something went wrong.

0 comments on commit 9455e2d

Please sign in to comment.