Yarnline (a Ravelry Mashup)

Aug 8, 2012 / By Yanick Champoux

Tags: ,

A while ago, I spotted TimelineJS, a JavaScript library to create gorgeous timelines, and earmarked it to a future app. Last week, I finally got to play with it by creating Yarnline, an itsy-bitsy mashup app that takes the projects of a Ravelry user and displays them in a chronological manner, like so:

Yarnline Screenshot

The app is running on my home server (but requires you to have a Ravelry account). The code itself is, for once, fairly banal. It’s using Dancer (and its beautiful, no-fuss serializing capacities), and HTML::Mason as its template system (which is slight overkill, considering that one of the pages of the app is purely static and the other one has one — yes, one — variable), with a dash of Dancer::Plugin::Cache::CHI to keep project lists around for a while. A slightly more interesting aspect is its use of Net::OAuth to communicate with Ravelry’s REST web service. (I also looked at Net::OAuth::Simple but in the end decided it wasn’t much simpler than its big brother.)

One wouldn’t know by looking at the code, but getting the OAuth was quite the challenge. Between the request tokens, the access tokens, and the passing of urls between the client, the service provider, and the app, I have to admit that at some points I was finding the whole thing oddly reminescent of this video. Mind you, the module documentation was generally helpful but left some questions unanswered, like how to retrieve your access token without running back to the web service every time you need it. After a few hours of head-desk interfacting, though, I think I figured it out:

use Net::OAuth::Client;
use Net::OAuth::AccessToken;

get '/auth' => sub {
    # that one is simple...
    redirect auth_client->authorize_url;
};

get '/auth/callback' => sub {

    # get the access token from the web service...
    my $access = auth_client->get_access_token(
        param( 'oauth_token' ),
        param( 'oauth_verifier' ),
    );

    # ... and keep the information you need to rebuild it
    session rav_token        => $access->token;
    session rav_token_secret => $access->token_secret;
    session username         => param 'username';

    forward '/';
};

get '/timeline/:raveler' => sub {

    # access_token() is the good part there
    my $projects = from_json(
        access_token->get(
            join '/', '/projects', $raveler, 'list.json'
        )->content
    );

    # and do something with $projects...
};

# and yes, those two functions just scream to
# be Dancer::Pluginified

sub auth_client() {
    my $rav = config->{ravelry};

    return Net::OAuth::Client->new(
        $rav->{tokens}{consumer_key},
        $rav->{tokens}{consumer_secret},
        site                => 'https://api.ravelry.com',
        request_token_path  => '/oauth/request_token',
        authorize_path      => '/oauth/authorize',
        access_token_path   => '/oauth/access_token',
        callback            => uri_for( $rav->{callback} ),
        session             => \&session,
    );
}

sub access_token {
    return Net::OAuth::AccessToken->new(
        client       => auth_client(),
        token        => session( 'rav_token' ),
        token_secret => session( 'rav_token_secret' ),
    );
}

Oh yeah, and today I began to switch the templates from Mason to my experiment-in-progress, Template::Caribou. How did that go? Well, that’s a story for another blog entry…

2 Responses to “Yarnline (a Ravelry Mashup)”

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>