SweetPotato::Plagger このページをアンテナに追加 RSSフィード

2008-04-22

Store::Fastladderを使っていてpermalinkとか未読記事とかに問題が出てきたのでパッチ作った 22:55 Store::Fastladderを使っていてpermalinkとか未読記事とかに問題が出てきたのでパッチ作った - SweetPotato::Plagger を含むブックマーク はてなブックマーク - Store::Fastladderを使っていてpermalinkとか未読記事とかに問題が出てきたのでパッチ作った - SweetPotato::Plagger Store::Fastladderを使っていてpermalinkとか未読記事とかに問題が出てきたのでパッチ作った - SweetPotato::Plagger のブックマークコメント

OpenFLとStore::Fastladderを組み合わせて使っていたんだけど,いくつか問題が出てきた。

  1. 未読記事が10件しか表示されない
  2. Filter::TruePermalinkを使ってもtrueなpermalinkがDBに格納されない
  3. 記事本文のHTMLコメントが見えてしまう
  4. 記事がStore::FastladderによってDBに格納される度に未読になる

1.は先日の記事でこちらを参考にして解決できたんだけど残りが問題。

DBにはMySQLを使ってるんだけど「MySQLの問題じゃねーだろー」と思ってOpenFL(Windows版 0.0.2)とStore::Fastladder(Revision 2029)のソースを眺めた。

関係してるのは以下の箇所かな。

app\controllers\api_controller.rb (line.31-33)

  def unread
    conditions = @sub.viewed_on ? ["stored_on >= ?", @sub.viewed_on] : nil
    items = @sub.feed.items.find(:all, :conditions => conditions, :order => "created_on DESC, id DESC", :limit => MAX_UNREAD_COUNT)

OpenFLは記事が未読か否かをstored_onカラムの値を見て判断すると。

lib\crawler.rb (line.174-176)

    items = items.reject { |item|
      feed.items.exists?(["link = ? and digest = ?", item.link, item.digest])
    }

OpenFLのクローラは,既に同じリンクの記事がDBに格納されていた場合,記事のdigestを比較する。そしてdigestが同じ(≒記事本文に変化なし)であれば,その記事はDBに格納しないと。

Plagger\Plugin\Store\Fastladder.pm (line.93-96)

        my $item = $self->rs('Items')->find_or_new({
            feed_id => $feed->id,
            link    => $entry->link,
        });

Store::Fastladderは$entry->permalinkではなく$entry->linkの値をDB格納していると。

というわけでこんなパッチに

--- Fastladder.pm.rev2029	Tue Apr 22 18:53:39 2008
+++ Fastladder.pm	Tue Apr 22 20:53:46 2008
@@ -92,29 +92,28 @@
     for my $entry (@{ $args->{feed}->entries }) {
         my $item = $self->rs('Items')->find_or_new({
             feed_id => $feed->id,
-            link    => $entry->link,
+            link    => $entry->permalink,
         });
 
         $item->set_columns({
             title          => $entry->title || '',
-            body           => $entry->body,
+            body           => do { my $body = $entry->body || '' ; $body =~ s/<!--.*?-->//g; $body },
             author         => $entry->author,
             category       => join(', ', @{$entry->tags}) || undef,
             digest         => $entry->digest,
             enclosure      => $entry->has_enclosure ? $entry->enclosure->url : undef,
             enclosure_type => $entry->has_enclosure ? $entry->enclosure->type : undef,
         });
-        $item->created_on( $entry->date || $now );
-        $item->modified_on( $entry->date || $now );
-        $item->stored_on( $now );
-        $item->updated_on( $now ) if $item->is_changed;
 
-        if ($item->is_column_changed('digest')) {
+        if (!$item->in_storage || $item->is_column_changed('digest')) {
+            $item->created_on( $entry->date || $now ) if !$item->in_storage;
+            $item->modified_on( $entry->date || $item->created_on );
+            $item->stored_on( $now );
+            $item->updated_on( $now );
             my $subs = $me->subscriptions({ feed_id => $feed->id })->first;
             $subs->update({ has_unread => ref($self->schema->storage) =~ /SQLite/ ? 'true' : \'true' }); # XXX
+            $item->insert_or_update;
         }
-
-        $item->insert_or_update;
     }
 
     # update status

記事本文のHTMLコメントは思い切って落とすことにした。ひょっとしたらOpenFL側で非表示にできるのかもしれないけど「どうせ表示されないなら格納時に落としちゃっていいじゃん」という発想。

ところでupdated_onカラムの存在意義を誰か教えてください。他のソースも頑張って読んだけどさっぱり分からない。

トラックバック - http://plagger.g.hatena.ne.jp/SweetPotato/20080422