Permalink
Browse files

Merge branch 'release/1.3094'

  • Loading branch information...
xsawyerx committed Mar 31, 2012
2 parents 59f4cb0 + f0b3422 commit cb7997473de61da75447f7702e929b8c75d16deb
View
@@ -67,6 +67,7 @@ A huge thank you to all of them!
Nicolas Oudard <noudard@weborama.com>
Niko <nikomomo@gmail.com>
Olivier Mengué <dolmen@cpan.org>
+ Ovid <ovid@cpan.org>
Paul Driver <frodwith@gmail.com>
Paul Tomlin <ptomli@gmail.com>
Philippe Bruhat (BooK) <book@cpan.org>
View
35 CHANGES
@@ -1,5 +1,40 @@
{{$NEXT}}
+1.3094 31.03.2012
+
+ [ BUG FIXES ]
+ * GH #763: Fix exceptions in ajax routes clobbering layout (ilmari)
+ * GH #748 & GH 647: Don't force override environment from PLACK_ENV (jwittkoski)
+ * GH #762: fix param parsing lacking limit on split (leejo)
+ * GH #758: Fix Dancer::Test: make sure the request is properly converted to
+ a response. (Ovid)
+ * GH #729: Fix dancer exception composition, and message pattern application
+ (Damien Krotkine)
+ * GH #752: Exceptions raised in hooks were not propagated back to the route
+ code, but instead canceleld and replaced by a Dancer halt exception. That
+ was wrong. Now it is fixed, exceptions raised in hooks can be properly
+ caught in route code.
+ (Damien Krotkine)
+ * Be more flexible in single vs. mutliple values in key hiding.
+ (Sam Kington)
+ * Use isa() for checking relationships instead of ref() in Dancer::Test.
+ (Ovid)
+
+ [ ENHANCEMENTS ]
+ * Added 'strict_config' option to have the config return an object instead
+ of a hashref. (Ovid)
+ * GH #708: Added support for query strings in dancer_request (Jacob Rideout)
+ * It's possible for the user to set the environments directory using a new
+ environment variable (DANCER_ENVDIR) or using `set envdir => $path`
+ * Sort hash keys when serializing references in log messages (Ovid).
+
+ [ DOCUMENTATION ]
+ * Explain in POD that if there are multiple fields with the same name,
+ params('fieldname') returns an arrayref of them (alexrj).
+ * GH #750: Fix in Dancer::Deployment: appdir needs to be set before calling
+ load_app (Paul Johnson)
+ * Update 'before' hook document (David Cantrell).
+
1.3093 29.02.2012
[ BUG FIXES ]
View
@@ -13,6 +13,7 @@ examples/dancr/views/show_entries.tt
lib/Dancer.pm
lib/Dancer/App.pm
lib/Dancer/Config.pm
+lib/Dancer/Config/Object.pm
lib/Dancer/Continuation.pm
lib/Dancer/Continuation/Halted.pm
lib/Dancer/Continuation/Route.pm
@@ -125,6 +126,8 @@ t/01_config/04_config_file.t
t/01_config/05_serializers.t
t/01_config/06_config_api.t
t/01_config/06_stack_trace.t
+t/01_config/07_strict_config.t
+t/01_config/08_environments.t
t/01_config/environments/development.pl
t/01_config/yaml_dependency.t
t/02_request/000_create_fake_env.t
@@ -173,9 +176,9 @@ t/03_route_handler/99_bugs.t
t/03_route_handler/public/404.html
t/03_route_handler/public/utf8file.txt
t/03_route_handler/views/error.tt
-t/03_route_handler/views/hello.tt
-t/03_route_handler/views/foo/index.tt
t/03_route_handler/views/foo/bar.tt
+t/03_route_handler/views/foo/index.tt
+t/03_route_handler/views/hello.tt
t/04_static_file/001_base.t
t/04_static_file/003_mime_types_reinit.t
t/04_static_file/01_mime_types.t
@@ -315,6 +318,7 @@ t/23_dancer_tests/02_tests_functions.t
t/24_deployment/01_multi_webapp.t
t/25_exceptions/01_exceptions.t
t/25_exceptions/02_exceptions.t
+t/25_exceptions/03_exceptions.t
t/25_exceptions/views/error.tt
t/25_exceptions/views/index.tt
t/25_exceptions/views/layouts/main.tt
View
@@ -5,7 +5,7 @@ use warnings;
use Carp;
use Cwd 'realpath';
-our $VERSION = '1.3093';
+our $VERSION = '1.3094';
our $AUTHORITY = 'SUKRIA';
use Dancer::App;
@@ -925,17 +925,17 @@ This hook receives as argument a L<Dancer::Error> object.
=item before
-This is an alias to C<before>.
+This hook receives one argument, a reference to the subroutine that
+implements the route that is being intercepted by this hook.
-This hook receives no arguments.
-
- before sub {
+ hook before => sub {
+ my $route_handler = shift;
...
};
-is equivalent to
+it is equivalent to the deprecated
- hook before => sub {
+ before sub {
...
};
View
@@ -5,6 +5,7 @@ use warnings;
use base 'Exporter';
use vars '@EXPORT_OK';
+use Dancer::Config::Object 'hashref_to_object';
use Dancer::Deprecation;
use Dancer::Template;
use Dancer::ModuleLoader;
@@ -143,16 +144,26 @@ sub conffile { path(setting('confdir') || setting('appdir'), 'config.yml') }
sub environment_file {
my $env = setting('environment');
- return path(setting('appdir'), 'environments', "$env.yml");
+ # XXX for compatibility reason, we duplicate the code from `init_envdir` here
+ # we don't know how if some application don't already do some weird stuff like
+ # the test in `t/15_plugins/02_config.t`.
+ my $envdir = setting('envdir') || path(setting('appdir'), 'environments');
+ return path($envdir, "$env.yml");
}
sub init_confdir {
return setting('confdir') if setting('confdir');
setting confdir => $ENV{DANCER_CONFDIR} || setting('appdir');
}
+sub init_envdir {
+ return setting('envdir') if setting('envdir');
+ setting envdir => $ENV{DANCER_ENVDIR} || path(setting('appdir'), 'environments');
+}
+
sub load {
init_confdir();
+ init_envdir();
# look for the conffile
return 1 unless -f conffile;
@@ -175,6 +186,9 @@ sub load {
foreach my $key (grep { $setters->{$_} } keys %$SETTINGS) {
$setters->{$key}->($key, $SETTINGS->{$key});
}
+ if ( $SETTINGS->{strict_config} ) {
+ $SETTINGS = hashref_to_object($SETTINGS);
+ }
return 1;
}
@@ -408,6 +422,11 @@ C<template> keyword. Check C<Dancer> manpage for details.
=head2 Logging, debugging and error handling
+=head2 strict_config (boolean, default: false)
+
+If true, C<config> will return an object instead of a hash reference. See
+L<Dancer::Config::Object> for more information.
+
=head3 import_warnings (boolean, default: enabled)
If true, or not present, C<use warnings> will be in effect in scripts in which
@@ -588,6 +607,16 @@ Dancer will honor your C<before_template_render> code, and all default
variables. They will be accessible and interpolated on automatic
served pages.
+=head2 DANCER_CONFDIR and DANCER_ENVDIR
+
+It's possible to set the configuration directory and environment directory using this two
+environment variables. Setting `DANCER_CONFDIR` will have the same effect as doing
+
+ set confdir => '/path/to/confdir'
+
+and setting `DANCER_ENVDIR` will be similar to:
+
+ set envdir => '/path/to/environments'
=head1 AUTHOR
View
@@ -0,0 +1,171 @@
+package Dancer::Config::Object;
+
+use strict;
+use warnings;
+
+use base 'Exporter';
+use Carp 'croak';
+use Dancer::Exception qw(:all);
+use Scalar::Util 'blessed';
+
+register_exception('BadConfigMethod',
+ message_pattern =>
+ qq{Can't locate config attribute "%s".\nAvailable attributes: %s});
+
+our @EXPORT_OK = qw(hashref_to_object);
+
+{
+ my $index = 1;
+
+ sub hashref_to_object {
+ my ($hashref) = @_;
+ my $class = __PACKAGE__;
+ my $target = "${class}::__ANON__$index";
+ $index++;
+ if ('HASH' ne ref $hashref) {
+ if ( blessed $hashref ) {
+ # we have already converted this to an object. This can happen
+ # in cases where Dancer::Config->load is called more than
+ # once.
+ return $hashref;
+ }
+ else {
+ # should never happen
+ raise 'Core::Config' => "Argument to $class must be a hashref";
+ }
+ }
+ my $object = bless $hashref => $target;
+ _add_methods($object);
+
+ return $object;
+ }
+}
+
+
+sub _add_methods {
+ my ($object) = @_;
+ my $target = ref $object;
+
+ foreach my $key ( keys %$object ) {
+ my $value = $object->{$key};
+ if ( 'HASH' eq ref $value ) {
+ $value = hashref_to_object($value);
+ }
+ elsif ( 'ARRAY' eq ref $value ) {
+ foreach (@$value) {
+ $_ = 'HASH' eq ref($_) ? hashref_to_object($_) : $_;
+ }
+ }
+
+ # match a (more or less) valid identifier
+ next unless $key =~ qr/^[[:alpha:]_][[:word:]]*$/;
+ my $method = "${target}::$key";
+ no strict 'refs';
+ *$method = sub {$value};
+ }
+ _setup_bad_method_trap($target);
+}
+
+# AUTOLOAD will only be called if a non-existent method is called. It's used
+# to generate the list of available methods. It's slow, but we're going to
+# die. Who wants to die quickly?
+sub _setup_bad_method_trap {
+ my ($target) = @_;
+ no strict; ## no critic (ProhibitNoStrict)
+ *{"${target}::AUTOLOAD"} = sub {
+ $AUTOLOAD =~ /.*::(.*)$/;
+
+ # should never happen
+ my $bad_method = $1 ## no critic (ProhibitCaptureWithoutTest)
+ or croak "Could not determine method called via $AUTOLOAD";
+ return if 'DESTROY' eq $bad_method;
+ my $symbol_table = "${target}::";
+
+ # In these fake classes, we only have methods
+ my $methods =
+ join ', ' => grep { !/^(?:AUTOLOAD|DESTROY|$bad_method)$/ }
+ sort keys %$symbol_table;
+ raise BadConfigMethod => $bad_method, $methods;
+ };
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Dancer::Config::Object - Access the config via methods instead of hashrefs
+
+=head1 DESCRIPTION
+
+If C<strict_config> is set to a true value in the configuration, the
+C<config()> subroutine will return an object instead of a hashref. Instead of
+this:
+
+ my $serializer = config->{serializer};
+ my $username = config->{auth}{username};
+
+You get this:
+
+ my $serializer = config->serializer;
+ my $username = config->auth->username;
+
+This helps to prevent typos. If you mistype a configuration name:
+
+ my $pass = config->auth->pass;
+
+An exception will be thrown, tell you it can't find the method name, but
+listing available methods:
+
+ Can't locate config attribute "pass".
+ Available attributes: password, username
+
+If the hash key cannot be converted into a proper method name, you can still
+access it via a hash reference:
+
+ my $some_value = config->{'99_bottles'};
+
+And call methods on it, if possible:
+
+ my $sadness = config->{'99_more_bottles'}->last_bottle;
+
+Hash keys pointing to hash references will in turn have those "objectified".
+Arrays will still be returned as array references. However, hashrefs inside of
+the array refs may still have their keys allowed as methods:
+
+ my $some_value = config->some_list->[1]->host;
+
+=head1 METHOD NAME DEFINITION
+
+We use the following regular expression to determine if a hash key qualifies
+as a method:
+
+ /^[[:alpha:]_][[:word:]]*$/;
+
+Note that this means C<naïve> (note the dots over the i) can be a method name,
+but unless you C<use utf8;> to declare that your source code is UTF-8, you may
+have disappointing results calling C<< config->naïve >>. Further, depending on
+your version of Perl and the software to read your config file ... well, you
+get the idea. We recommend sticking with ASCII identifiers if you wish your
+code to be portable.
+
+Patches/suggestions welcome.
+
+=head1 AUTHOR
+
+This module has been written by Alexis Sukrieh <sukria@cpan.org> and others,
+see the AUTHORS file that comes with this distribution for details.
+
+=head1 LICENSE
+
+This module is free software and is released under the same terms as Perl
+itself.
+
+=head1 SEE ALSO
+
+L<Dancer> and L<Dancer::Config>.
+
+=cut
@@ -179,8 +179,8 @@ Start by creating a simple app.psgi file:
my $app1 = sub {
my $env = shift;
local $ENV{DANCER_APPDIR} = '/Users/franck/tmp/app1';
- load_app "app1";
setting appdir => '/Users/franck/tmp/app1';
+ load_app "app1";
Dancer::App->set_running_app('app1');
Dancer::Config->load;
my $request = Dancer::Request->new( env => $env );
@@ -190,8 +190,8 @@ Start by creating a simple app.psgi file:
my $app2 = sub {
my $env = shift;
local $ENV{DANCER_APPDIR} = '/Users/franck/tmp/app2';
- load_app "app2";
setting appdir => '/Users/franck/tmp/app2';
+ load_app "app2";
Dancer::App->set_running_app('app2');
Dancer::Config->load;
my $request = Dancer::Request->new( env => $env );
Oops, something went wrong.

0 comments on commit cb79974

Please sign in to comment.