From 0afbfaee75e8480e8e0ed0a3bbd3749a4756f727 Mon Sep 17 00:00:00 2001
From: franck cuny <franck@lumberjaph.net>
Date: Fri, 10 Sep 2010 23:25:10 +0200
Subject: initial import

---
 ...feed-aggregator-with-modern-perl-part-4.textile | 187 +++++++++++++++++++++
 1 file changed, 187 insertions(+)
 create mode 100644 _posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.textile

(limited to '_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.textile')

diff --git a/_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.textile b/_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.textile
new file mode 100644
index 0000000..ca7849e
--- /dev/null
+++ b/_posts/2009-05-13-a-simple-feed-aggregator-with-modern-perl-part-4.textile
@@ -0,0 +1,187 @@
+---
+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 <a href="/feed/">your feeds</a>
+
+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 %}
+    <Model KiokuDB>
+        dsn dbi:SQLite:../MyAggregator/foo.db
+    </Model>
+{% 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 %}
+<Model MyModel>
+    connect_info dbi:SQLite:../MyModel/model.db
+    schema_class MyModel
+</Model>
+{% 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 %}
+<ul>
+    [% FOREACH feed IN feeds %]
+        <li><a href="/feed/view/[% feed.id %]">[% feed.url %]</a></li>
+    [% END %]
+</ul>
+{% endhighlight %}
+
+*root/src/feed/vew.tt2*
+
+{% highlight perl %}
+<h1>[% feed.url %]</h1>
+
+<h3>entries</h3>
+<ul>
+    [% FOREACH entry IN feed.entries %]
+        <li><a href="/entry/[% entry.id %]">[% entry.permalink %]</a></li>
+    [% END %]
+</ul>
+{% 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 %}
+<h1><a href="[% entry.permalink %]">[% entry.title %]</a></h1>
+<span>Posted [% entry.date %] by [% entry.author %]</span>
+<div id="content">
+    [% entry.content %]
+</div>
+{% 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

