Yancy::Guides::Cookbook - Recipes for Yancy apps
version 1.088
Create another instance of the Yancy editor using Yancy::Plugin::Editor, passing in a new route, a moniker, and the exact schemas and fields you want to allow.
# Allow content editors to only edit the title, content, and # content_html of blog posts my $schema = app->yancy->schema; my $editable_properties = { %{ $schema->{blog_posts}{properties} }{qw( blog_post_id title content content_html )}, }; app->yancy->plugin( Editor => { backend => app->yancy->backend, route => '/edit', require_user => { -bool => 'is_editor', }, schema => { blog_posts => { %{ $schema->{blog_posts} }, properties => $editable_properties, }, }, } );
See https://github.com/preaction/Yancy/tree/master/eg/limited-editor for the complete example.
To handle a custom search form for the Yancy controller "list" action there are two options:
under
filter
In this option, we use Mojolicious's "under" route to handle the form before the final action is called.
# Download this example: https://github.com/preaction/Yancy/tree/master/eg/cookbook/custom-filter-lite.pl use Mojolicious::Lite -signatures; # Download log.sqlite3: https://github.com/preaction/Yancy/tree/master/eg/cookbook/log.sqlite3 plugin Yancy => { backend => 'sqlite:log.sqlite3', read_schema => 1 }; under sub( $c ) { my $levels = $c->every_param( 'log_level' ); if ( @$levels ) { # Include only log levels requested $c->stash( filter => { log_level => $levels } ); } return 1; }; get '/' => { controller => 'Yancy', action => 'list', schema => 'log', template => 'log', }; app->start; __DATA__ @@ log.html.ep %= form_for current_route, begin % for my $log_level ( qw( debug info warn error ) ) { %= label_for "log_level_$log_level", begin %= ucfirst $log_level %= check_box log_level => $log_level % end % } %= submit_button 'Filter' % end %= include 'yancy/table'
In this option, we extend the Yancy controller to add our own action. Then, we can call the action we want to end up at (in this case, the "list" action).
# Download this example: https://github.com/preaction/Yancy/tree/master/eg/cookbook/custom-filter-full.pl use Mojo::Base -signatures; package MyApp::Controller::Log { use Mojo::Base 'Yancy::Controller::Yancy', -signatures; sub list_log( $self ) { my $levels = $self->every_param( 'log_level' ); if ( @$levels ) { # Include only log levels requested $self->stash( filter => { log_level => $levels } ); } return $self->SUPER::list; } } package MyApp { use Mojo::Base 'Mojolicious', -signatures; sub startup( $self ) { push @{ $self->renderer->classes }, 'main'; push @{ $self->routes->namespaces }, 'MyApp::Controller'; # Download log.db: http://github.com/preaction/Yancy/tree/master/eg/cookbook/log.sqlite3 $self->plugin( Yancy => { backend => 'sqlite:log.sqlite3', read_schema => 1, } ); $self->routes->get( '/' )->to( controller => 'Log', action => 'list_log', schema => 'log', template => 'log', ); } } Mojolicious::Commands->new->start_app( 'MyApp' ); __DATA__ @@ log.html.ep %= form_for current_route, begin % for my $log_level ( qw( debug info warn error ) ) { %= label_for "log_level_$log_level", begin %= ucfirst $log_level %= check_box log_level => $log_level % end % } %= submit_button 'Filter' % end
Create a schema for the pages (perhaps, named pages). This schema must at least have an ID (perhaps in page_id), a path (in a path field), and some content (in a content field). We should use the path field as Yancy's ID field so that we can more easily look up the pages.
pages
page_id
path
content
# Download this database: https://github.com/preaction/Yancy/tree/master/eg/cookbook/pages.sqlite3 use Mojolicious::Lite -signatures; plugin Yancy => { backend => 'sqlite:pages.sqlite3', schema => { pages => { title => 'Pages', description => 'These are the pages in your site.', 'x-id-field' => 'path', required => [qw( path content )], properties => { page_id => { type => 'integer', readOnly => 1, }, path => { type => 'string', }, content => { type => 'string', format => 'html', }, }, }, }, };
Once we have a schema, we need to render these pages. We want these pages to show up when the user visits the page's path, so we need a route that captures everything. Because our route captures everything, it should be the last route we declare (Mojolicious routes are checked in-order for matching). We also want to allow a default path of "index", so we give a default value for the path stash.
app->routes->get( '/*path', { path => 'index' } )->to({ controller => 'Yancy', action => 'get', schema => 'pages', template => 'page', });
Now we need a template to display the content. There isn't much to this template:
@@ page.html.ep %== $item->{content}
View the example of user-editable pages
If you want your users to use Markdown instead of HTML, add another field for the Markdown (called markdown), and have the editor render the Markdown into HTML in the content field.
markdown
use Mojolicious::Lite -signatures; # Download this database: https://github.com/preaction/Yancy/tree/master/eg/cookbook/pages-md.sqlite3 plugin Yancy => { backend => 'sqlite:pages-markdown.sqlite3', schema => { pages => { title => 'Pages', description => 'These are the pages in your site.', required => [qw( path markdown )], properties => { page_id => { type => 'integer', readOnly => 1, }, path => { type => 'string', }, markdown => { type => 'string', format => 'markdown', 'x-html-field' => 'content', }, content => { type => 'string', format => 'html', }, }, }, }, };
View the example of pages with Markdown
Doug Bell <preaction@cpan.org>
This software is copyright (c) 2021 by Doug Bell.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Yancy, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Yancy
CPAN shell
perl -MCPAN -e shell install Yancy
For more information on module installation, please visit the detailed CPAN module installation guide.