From 8ddf2e94df70707b458528a437759b96046d3e01 Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Tue, 26 Nov 2013 10:36:10 -0800 Subject: Huge update. Moved all posts from textile to markdown. Updated all the CSS and styles. Added a new page for the resume. --- ...mple-feed-aggregator-with-modern-perl-part-4.md | 189 +++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 _posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.md (limited to '_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.md') diff --git a/_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.md b/_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.md new file mode 100644 index 0000000..aace6ea --- /dev/null +++ b/_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.md @@ -0,0 +1,189 @@ +--- +layout: post +title: A simple feed aggregator with modern Perl - part 4 +summary: In which we reach the conclusion on how to write a feed aggregator. +--- + +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** + +{% highlight html %} +to your feeds +{% endhighlight %} + +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 xml %} + + 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 xml %} + + 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 html %} + +{% endhighlight %} + +**root/src/feed/vew.tt2** + +{% highlight html %} +

[% 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 html %} +

[% 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) -- cgit v1.2.3