25 posts tagged ruby

Weary: The Road to 1.0

In the coming weeks, I plan on blocking out time to focus on Weary, my original Ruby pet project. Weary is the little REST consumer that powers the Tumblr Gem. I’ve written about Weary before. I have neglected it a bit since the release of tumblr-rb, but I’ve got a lot planned to get Weary to a 1.0 release. Here is what needs to be in Weary before it can reach that level:

1. Dynamic URL’s.

This is what your basic Weary Resource call looks like, taken from Tumblr::Writer:

post :delete do |del|
    del.url = 'http://www.tumblr.com/api/delete'
    del.requires = [:email, :password, :'post-id']
end

When you instantiate Tumblr::Writer that object now gets a method called delete:

write = Tumblr::Writer.new
write.delete :email => "test@testymcgee.com", :password => "s3cret", :'post-id' => 1234

Above, in the Resource declaration, it says that the keys :email, :password, and :'post-id' are required. When you call the delete method, if you do not provide a Hash containing all of the required keys as an argument, it will raise an exception.

The problem comes when there is a parameter that is not sent as an HTTP POST body or GET query, but as a segment of the URL. Such is the case with Tumblr’s Authenticated Reads. For a read, you must provide the username in the host of the url: http://#{username}.tumblr.com/api/read/.

The way I’ve handled this is by creating a method that falls back to Weary’s module methods:

def self.read(username, via = :get, params = {})
  Weary.request("http://#{username}.tumblr.com/api/read/", via) do |req|
    req.with = params unless params.blank?
  end
end

This is not optimal, and makes these methods an outlier from the preferred Weary way of doing things. Weary will handle this in a future release using the Addressable gem. Wynn has been toying with this a bit, but it has yet to be merged in.

post :authenticated_read do |r|
    r.url = "http://{username}.tumblr.com/api/read/"
    r.with = [:start,:num,:type,:id,:filter,:tagged,:search,:state]
    r.requires = [:email, :password]
end

Along with the required :email and :password keys, the Resource declaration says that a new key is required: :username, that builds the URL for the request.

reader = Tumblr::Reader.new
reader.authenticated_read :email => "test@testymcgee.com", :password => "s3cret", :username => "mwunsch"

2. Defaults at the Resource level.

Right now, it’s easy to save default key-value pairs that get sent with every request. It’s how the Tumblr Gem does a lot of its mojo. But maybe you want to have some default pairs that get sent with every resource, defined at the Class level. Weary will add a new defaults method to Resources.

post :dashboard do |dashboard|
    dashboard.url = "http://www.tumblr.com/api/dashboard"
    dashboard.requires = [:email,:password]
    dashboard.with = [:start,:num,:type,:filter,:likes]
    dashboard.defaults = {:num => 50, :likes = 1}
end

3. HTTP Connection Adapters

This is the new feature I am most excited about. Right now Weary::Request and Weary::Resource is a thin layer of syntactic sugar that sits above the standard Net::HTTP library. I’ll be working on abstracting away Net::HTTP into a Weary::Adapter class. When triggering Request#perform, it will defer to the adapter for how to form and make the Request. The Request and Resource classes will truly be abstract, and this allows us to build adapters for different HTTP libraries. So imagine doing something like this:

class Reader < Weary::Base
    adapter :typhoeus
end

I’ll be working hard on defining an API for creating Adapters. Weary will default to the Net::HTTP adapter, and will come with a Typhoeus adapter. This is similar to how Faraday does it’s magic, but with the sickly sweet Weary API we’ve all come to know and love.

4. Self-documenting

This has been an intended feature of Weary for a long time, and it will be a part of moving to 1.0. Weary will hook into the YARD documentation tool, and when defining a Resource, it will generate documentation. So not only can you create a Ruby library for your API, by creating the library you are also writing documentation for your API.

Keep an eye on Weary for the next month or so as these features trickle in, inching closer to 1.0.

How I use Bundler

For those familiar with Ruby and/or Rails, I’m sure you’ve heard of the fantastic new Bundler tool, by the wonder twins of Ruby development, Carl Lerche and Yehuda Katz (collectively: carlhuda).

Bundler is the new way to manage an application’s dependencies for Rails 3, and is integrated right into the framework.

But Bundler does not need to be just a Rails utility or even just an application utility. All of my Ruby projects are now using Bundler to handle their development dependencies.

I was won over by Ryan Tomayko’s now-famous-amongst-rubyists doctrine that states that require 'rubygems' should not find its way into a library; a lib is not in charge of wrangling the Ruby $LOAD_PATH. But for developers who want to work on my open-source projects, I want to make sure they have everything they need to run my test suite or build tasks. Bundler has helped me succeed with that.

Rubygems does not infiltrate my library. Development dependencies, like ronn or contest, are listed in a Gemfile. When you gem install one of my projects, you’re not installing any more than the lib requires. If you’d like to contribute or hack on one of my projects, clone it and run bundle install to get all the dependencies you need. Bundler provides a simple way to keep the development work on a library isolated to a sandbox.

If you are a Ruby developer working on a library or gem, you should look into Bundler as a great way to package your development dependencies so others can work on your project without hassle.

Redwood: Ruby Trees

Redwood is my newest project: a simple implementation of a tree data structure in pure Ruby. It provides a few things:

  • The redwood command-line tool: a Ruby hack/rewrite of the Unix tree program.
  • A Module providing tree-like methods for your objects.
  • A Redwood::Node class as a basic implementation of tree creation.
  • A Redwood::FileNode class for representing directories in a tree-like way.

gem install redwood to get started.

Learn about, enjoy, and fork the redwood project over at GitHub. For help with the redwood CLI, read the redwood(1) manpage.

My favorite thing about Redwood is that you get the awesome tree view for all of the tree objects that mix-in Redwood:

Redwood
|-- bin
|   `-- redwood
|-- Gemfile
|-- lib
|   |-- redwood
|   |   |-- filenode.rb
|   |   `-- node.rb
|   `-- redwood.rb
|-- LICENSE
|-- pkg
|   `-- redwood-0.0.1.gem
|-- Rakefile
|-- README.md
|-- redwood.gemspec
`-- test
    |-- helper.rb
    `-- test_redwood.rb

Redwood was created mostly to facilitate this kind of thing, and as a bit of a brain-teaser. The redwood CLI is, honestly, totally inferior to the original tree (written in C). I was getting frustrated working on Prism, and I created Redwood to get my mind wrapped around the concept of tree structures. While there are several implementations of tree data-structures in Ruby, I wasn’t really impressed with any of their APIs. And none of them created the tree-view that you get with the Redwood#view method.

Redwood began life as a thought-experiment and I hope you are able to use it whenever you need something resembling a tree.

Tumblr Gem v1.2.0

Tumblr Gem has been updated with support for the new API methods.

gem update tumblr-rb

This isn’t useful for the CLI, but for those who use Tumblr Gem as a Ruby library. To call the new methods:

user = Tumblr.new(email, password)
user.pages(username)

Or for the authenticated read of pages (as described in the API):

user.all_pages(username)

Also new, the Authenticator class can pass the include-theme parameter. Here’s the preferred method:

user.authenticate(true) 
# Passing true to authenticate will include theme info.

Enjoy.

wp2tumblr: WordPress to Tumblr import script

Here’s a little command-line tool for importing WordPress posts to Tumblr. It works okay. Download it, chmod 755, and run it like this:

$: ./wp2tumblr wordpress.xml

Where wordpress.xml is a WordPress XML export. You can pass an optional --group parameter if you want to publish to a blog other than your main.

Some caveats:

  • All posts are regular posts.
  • Some post meta information is lost in the ether.
  • Comments are lost.
  • Anything not set to published will be saved as a Tumblr draft.

Update: I’ve updated the script to throttle requests to try to stay within the rate limit on api/write.

If there are less than 60 posts to import, this script uses Weary’s batch method for asynchronous requests. Each request is performed in its own thread (or your Ruby VM of choice’s approximation of a Thread). In other words, the script is really fast if you have less than 60 posts, but if not, will take 1 second per post to make sure you don’t exceed the rate limit.

Update: The good folks at Tumblr upped the rate limit on api/write from 10 to 60. Thanks Marco!

tumblrpurge

This little script is dangerous. It will destroy every Tumblr post in a given blog.

Download it, chmod 755 on it to make it executable, and be careful. I take no responsibility for you shooting yourself in the foot. Backup before you do anything.

$: ./tumblrpurge mwunsch

I don’t know why you would want to do something like this.

The script requires the Tumblr Gem v1.1.0.

The Tumblr Gem

Last night, I released the Tumblr gem, a command line utility and Ruby library for interacting with Tumblr. Here’s what it does:

$ tumblr my_post.txt

That will publish my_post.txt to Tumblr. Simple.

You can also give it a URL:

$ tumblr http://mwunsch.github.com/tumblr/tumblr.1.html

That will create a Link post on Tumblr pointing to the tumblr manpage.

Or create a Video post by giving it a YouTube or Vimeo URL:

$ tumblr http://www.youtube.com/watch?v=CW0DUg63lqU

Easy publishing to Tumblr on the command line.

Get Started

You need Ruby and Rubygems installed:

$ gem install tumblr-rb 

Read through tumblr(1) to get an idea of what you can do.

How it works

tumblr does a pretty good job of inferring what kind of post you want to make, as shown above, but you can add more options to your document by adding a little bit of YAML frontmatter, in the style of Jekyll. You can do things like specify a post-type, tagging posts, saving posts to your queue, etc. Read more about post formatting in tumblr(5).

Why?

Most of my Tumblr posts begin life as little notes in Notational Velocity (combined with Simplenote). I write them in Markdown, and then copy and paste them into Tumblr.com. It feels tedious. Now, with tumblr, I write a post in TextMate and can publish it immediately, with very little effort.

This post began life as a gist, and was published via the command line with tumblr.

The Tumblr gem was created as a kind-of-sort-of proof-of-concept for Weary, a Ruby library I wrote for simple RESTful web service consumption. Tumblr (the gem), is a robust Ruby wrapper supporting full coverage of the Tumblr API. The tumblr command line tool is a client of the Tumblr Ruby library (and comes packaged with it). I published this post with tumblr. In software, this is called “eating your own dogfood”.

The Tumblr Gem (my more-or-less official name for it; I also sometimes refer to it as “tumblr-rb”), is Open Source, available under an MIT License. The source code is available on GitHub.

Follow me on Twitter @markwunsch and on Tumblr for updates on all of my Open Source projects.