--- layout: post title: A simple feed aggregator with modern Perl - part 4 category: perl --- We have the model, the aggregator (and some tests), now we can do a basic frontend to read our feed. For this I will create a webapp using "catalyst":http://www.catalystframework.org. "Catalyst::Devel":http://search.cpan.org/perldoc?Catalyst::Devel is required for developping catalyst application, so we will install it first: {% highlight perl %} cpan Catalyst::Devel {% endhighlight %} Now we can create our catalyst application using the helper: {% highlight perl %} catalyst.pl MyFeedReader {% endhighlight %} This command initialise the framework for our application *MyFeedReader*. A number of files are created, like the structure of the MVC directory, some tests, helpers, ... We start by creating a view, using "TTSite":http://search.cpan.org/perldoc?Catalyst::View::TT. TTSite generate some templates for us, and the configuration for this template. We will also have a basic CSS, a header, footer, etc. {% highlight bash %} cd MyFeedReader perl script/myfeedreader_create.pl view TT TTSite {% endhighlight %} TTSite files are under *root/src* and *root/lib*. A *MyAggregator/View/TT.pm* file is also created. We edit it to make it look like this: {% highlight perl %} __PACKAGE__->config({ INCLUDE_PATH => [ MyFeedReader->path_to( 'root', 'src' ), MyFeedReader->path_to( 'root', 'lib' ) ], PRE_PROCESS => 'config/main', WRAPPER => 'site/wrapper', ERROR => 'error.tt2', TIMER => 0, TEMPLATE_EXTENSION => '.tt2', }); {% endhighlight %} Now we create our first template, in *root/src/index.tt2* bq. to your feeds If you start the application (using _perl script/myfeedreader_server.pl_) and point your browser on http://localhost:3000/, this template will be rendered. We need two models, one for KiokuDB and another one for MyModel: *lib/MyFeedReader/Model/KiokuDB.pm* {% highlight perl %} package MyFeedReader::Model::KiokuDB; use Moose; BEGIN { extends qw(Catalyst::Model::KiokuDB) } 1; {% endhighlight %} we edit the configuration file (*myfeedreader.conf*), and set the dsn for our kiokudb backend {% highlight perl %} dsn dbi:SQLite:../MyAggregator/foo.db {% endhighlight %} *lib/MyFeedReader/Model/MyModel.pm* {% highlight perl %} package MyFeedReader::Model::MyModel; use base qw/Catalyst::Model::DBIC::Schema/; 1; {% endhighlight %} and the configuration: {% highlight perl %} connect_info dbi:SQLite:../MyModel/model.db schema_class MyModel {% endhighlight %} We got our view and our model, we can do the code for the controller. We need 2 controller, one for the feed, and one for the entries. The Feed controller will list them and display entries titles for a given feed. The Entry controller will just display them. *lib/MyFeedReader/Controller/Feed.pm* {% highlight perl %} package MyFeedReader::Controller::Feed; use strict; use warnings; use parent 'Catalyst::Controller'; __PACKAGE__->config->{namespace} = 'feed'; sub index : Path : Args(0) { my ( $self, $c ) = @_; $c->stash->{feeds} = [ $c->model('MyModel')->resultset('Feed')->search() ]; } sub view : Chained('/') : PathPart('feed/view') : Args(1) { my ( $self, $c, $id ) = @_; $c->stash->{feed} = $c->model('MyModel')->resultset('Feed')->find($id); } 1; {% endhighlight %} The function *index* list the feeds, while the function *view* list the entries for a give feed. We use the chained action mechanism to dispatch this url, so we can have urls like this _/feed/*_ We create our 2 templates (for index and view): *root/src/feed/index.tt2* {% highlight perl %} {% endhighlight %} *root/src/feed/vew.tt2* {% highlight perl %}

[% feed.url %]

entries

{% endhighlight %} If you point your browser to bc. http://localhost:3000/feed/ you will see this: !/static/imgs/list_feed.png(list feeds)! Now the controller for displaying the entries: {% highlight perl %} package MyFeedReader::Controller::Entry; use strict; use warnings; use MyAggregator::Entry; use parent 'Catalyst::Controller'; __PACKAGE__->config->{namespace} = 'entry'; sub view : Chained('/') : PathPart('entry') : Args(1) { my ( $self, $c, $id ) = @_; $c->stash->{entry} = $c->model('KiokuDB')->lookup($id); } 1; {% endhighlight %} The function *view* fetch an entry from the kiokudb backend, and store it in the stash, so we can use it in our template. *root/src/entry/view.tt2* {% highlight perl %}

[% entry.title %]

Posted [% entry.date %] by [% entry.author %]
[% entry.content %]
{% endhighlight %} If you point your browser to an entry (something like *http://localhost:3000/entry/somesha256value*), you will see an entry: !/static/imgs/show_entry.png(show entry)! Et voila, we are done with a really basic feed reader. You can add methods to add or delete feed, mark an entry as read, ... "The code is available on github":http://github.com/franckcuny/ironman-myfeedreader/tree/master