Skip to content

Commit

Permalink
allow additional backends in controller, editor
Browse files Browse the repository at this point in the history
Adding custom backends to the editor required adding them to the
controller as well. Adding custom backends to the controller required
allowing a request-wide backend so that all the backend helpers (list,
get, set, create, delete) would work correctly. This may prove to be
a terrible decision, as it means that a controller can only ever work
with one backend at a time, but we'll see how it goes...
  • Loading branch information
preaction committed Jun 24, 2019
1 parent 85b78c3 commit 5ad5242
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 13 deletions.
14 changes: 11 additions & 3 deletions lib/Mojolicious/Plugin/Yancy.pm
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ C<schema> configuration as needed.
my $be = $c->yancy->backend;
Get the currently-configured Yancy backend object. See L<Yancy::Backend>
for the methods you can call on a backend object and their purpose.
Get the Yancy backend object. By default, gets the backend configured
while loading the Yancy plugin. Requests can override the backend by
setting the C<backend> stash value. See L<Yancy::Backend> for the
methods you can call on a backend object and their purpose.
=head2 yancy.plugin
Expand Down Expand Up @@ -586,7 +588,13 @@ sub register {
# Load the backend and schema
$config = { %$config };
$app->helper( 'yancy.backend' => sub {
state $backend = load_backend( $config->{backend}, $config->{schema} || $config->{openapi}{definitions} );
my ( $c ) = @_;
state $default_backend = load_backend( $config->{backend}, $config->{schema} || $config->{openapi}{definitions} );
if ( my $backend = $c->stash( 'backend' ) ) {
$c->app->log->debug( 'Using override backend from stash: ' . ref $backend );
return $backend;
}
return $default_backend;
} );
if ( $config->{schema} || $config->{read_schema} ) {
$config->{schema} = $config->{schema} ? dclone( $config->{schema} ) : {};
Expand Down
8 changes: 7 additions & 1 deletion lib/Yancy/Plugin/Editor.pm
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ has moniker => 'editor';
has route =>;
has includes => sub { [] };
has menu_items => sub { +{} };
has backend =>;
has schema =>;

sub _helper_name {
my ( $self, $name ) = @_;
Expand All @@ -176,6 +178,9 @@ sub _helper_name {
sub register {
my ( $self, $app, $config ) = @_;

$self->backend( $config->{backend} );
$self->schema( $config->{schema} );

for my $key ( grep exists $config->{ $_ }, qw( moniker ) ) {
$self->$key( $config->{ $key } );
}
Expand All @@ -184,6 +189,7 @@ sub register {
derp 'api_controller configuration is deprecated. Use editor.default_controller instead';
}

# XXX: Throw an error if there is already a route here
my $route = $config->{route} // $app->routes->any( '/yancy' );
$route->to( return_to => $config->{return_to} // '/' );

Expand Down Expand Up @@ -232,7 +238,7 @@ sub register {
$self->_openapi_spec_add_mojo( $spec, $config );

my $openapi = $app->plugin( OpenAPI => {
route => $route->any( '/api' )->name( 'yancy.api' ),
route => $route->any( '/api' )->to( backend => $self->backend )->name( 'yancy.api' ),
spec => $spec,
default_response_name => '_Error',
} );
Expand Down
17 changes: 8 additions & 9 deletions t/lib/Yancy/Backend/Test.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ our @SCHEMA_ADDED_COLLS;

sub new {
my ( $class, $url, $schema ) = @_;
my ( $path ) = $url =~ m{^[^:]+://[^/]+(?:/(.+))?$};
if ( $path ) {
%DATA = %{ from_json( path( ( $ENV{MOJO_HOME} || () ), $path )->slurp ) };
} elsif ( %Yancy::Backend::Test::SCHEMA ) {
# M::P::Y relies on "read_schema" to give back the "real" schema.
# If given the micro thing, this is needed to make it actually
# operate like it would with a real database
$schema = \%Yancy::Backend::Test::SCHEMA;
if ( $url ) {
my ( $path ) = $url =~ m{^[^:]+://[^/]+(?:/(.+))?$};
if ( $path ) {
%DATA = %{ from_json( path( ( $ENV{MOJO_HOME} || () ), $path )->slurp ) };
}
}
$schema //= \%SCHEMA;
return bless { init_arg => $url, schema => $schema }, $class;
}

Expand Down Expand Up @@ -193,7 +191,8 @@ sub _is_type {

sub read_schema {
my ( $self, @table_names ) = @_;
my $cloned = dclone $self->collections;
my $schema = %SCHEMA ? \%SCHEMA : $self->schema;
my $cloned = dclone $schema;
delete @$cloned{@SCHEMA_ADDED_COLLS}; # ones not in the "database" at all
# zap all things that DB can't know about
for my $c ( values %$cloned ) {
Expand Down
56 changes: 56 additions & 0 deletions t/plugin/editor.t
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,60 @@ subtest 'menu' => sub {
;
};

subtest 'non-default backend' => sub {
my $new_schema = {
pets => {
required => [qw( name type )],
properties => {
id => {
type => 'integer',
readOnly => 1,
},
name => {
type => 'string',
},
type => {
type => 'string',
enum => [qw( cat dog bird rat snake )],
},
},
},
};

my $ted = {
name => 'Theodore',
type => 'cat',
};
my $franklin = {
name => 'Franklin',
type => 'cat',
};

my $new_backend = Yancy::Backend::Test->new( undef, $new_schema );
$ted->{id} = $new_backend->create( pets => $ted );
$franklin->{id} = $new_backend->create( pets => $franklin );

my $app = Mojolicious->new;
$app->plugin( Yancy => { %backend_conf } );
$app->yancy->plugin( Editor => {
backend => $new_backend,
schema => $new_schema,
moniker => 'pets',
require_user => undef,
route => $app->routes->get( '/pets/editor' ),
} );

my $t = Test::Mojo->new( $app );
$t->get_ok( '/yancy/api' )->status_is( 200 )
->json_has( '/definitions/people', 'got original schema at original url' )
->or( sub { diag explain shift->tx->res->json } )
->get_ok( '/pets/editor/api' )->status_is( 200 )
->json_has( '/definitions/pets', 'got new schema at new url' )
->or( sub { diag explain shift->tx->res->json } )
->get_ok( '/pets/editor/api/pets/' . $ted->{id} )->status_is( 200 )
->json_is( $ted )
->or( sub { diag explain shift->tx->res->json } )
;
};

done_testing;

0 comments on commit 5ad5242

Please sign in to comment.