Receiving Pingbacks on Rails sites

If you’ve never heard of pingbacks before, you’re out. Go home.

Ok, pingbacks are this mysterical feature when you write on your blog A and refer to some article on blog B. After you publish your article on blog A, something happens behind the curtain. Suddenly there’s a new comment on the blog B article you cited in your text, and this comment links back to your article on your blog A. That’s called a pingback.

Whereas sending a pingback is just a modest effort by fireing some small XML-RPC request, receiving is quite a bunch of work. A pingback’able site needs to

  • provide an XML-RPC capable server to receive pings
  • check the refering site’s article for the link to us
  • excerpt a piece of content from this refering article on blog A
  • store the extracted content with the link on the pinged page, maybe as a comment

Fortunately, there’s already a Rails plugin to handle this tedious task, namely pingback_engine which I wrote as a christmas gift for my friends on the net.

Receiving Pingbacks with pingback_engine

To make our Rails app pingback’able we need to install the engine, setup the server url propagation and then hook in a method for processing incoming pings. That is awesomely easy.

Installation

Inside the rails app directory install the engine, and a needed gem.

script/plugin install git://github.com/apotonick/pingback_engine.git
gem install hpricot

Your Rails app is now capable of receiving pingbacks via XML-RPC.

Propagating the server for auto-discovery

However, if a blog links to you, this blog will usually scan your page to discover the XML-RPC pingback server. What a pingback’able page should do to propagate this url is described in the pingback specification.

It roughly says, to define a pingback-enabled page

  • either return a X-Pingback HTTP header
  • or provide a special link element in the page HTML header
  • or do both!

In our example, we’re on the safe side by providing both. I instruct my blog controller to send an X-Pingback header by calling set_xpingback_header in the action that shows my articles.

# file: app/controllers/blog_controller.rb

class BlogController
    include PingbackHelper
    helper :pingback

    def article
      set_xpingback_header
      # ...

This will send the respective header with the correct url as soon as some blog tries to auto-discover the address for your XML-RPC pingback server.

Additionally, we provide a special <link ..> element in our application layout so the XML-RPC address is visible everywhere in the app.

# file: app/views/layouts/application.html.erb

      ...
      

Now other blogs will find your pingback server if some article links to your site.

Processing an incoming pingback
The only thing we have to implement is the pingback processing method. It’s currently put at the bottom of the rails environment file. Of course I could just delegate to another class method in some model, but for demonstration purpose it’s all in one file.

# file: config/environment.rb.

# ...
Pingback.save_callback do |ping|
    comment = ArticleComment.new
    comment.author     = ping.title
    comment.author_url = ping.source_uri
    comment.text       = ping.content
    comment.created_at = ping.time

    referenced_article = Article.find_by_url(ping.target_uri)

    if referenced_article
      comment.article_id = referenced_article.id
      comment.save

      ping.reply_ok # report success.
    else
      # report error:
      ping.reply_target_uri_does_not_accept_posts
    end
  end

Easy. Into the block to Pingback.save_callback we get a ping instance, which is enough to process, check and store the incoming pingback.
I just

  • create an ArticleComment instance, which is an ActiveRecord-derived class and represents comments in my blog (line 22)
  • assign -or map- values from ping to the comment
  • check the ping if it really points to an article in my blog
  • decide the incoming ping is invalid and discard it (line 37)
  • or save the comment in my blog and report success (line 34)

Anyway, all we have to do now is to login to some blog (recent WordPress blogs work great) and publish an article that links to a pingback’able page on our Rails site. The blog will send us all the information we need to receive the ping, and the pingback_engine will almost do the rest!

Testing manually
For debugging or testing purposes you can also use a test script shipped with the plugin. All you need is your set up rails site and a HTML page accessable on some webserver. The HTML page must link to a pingback-enabled page on your rails site.

By firing

pingback_engine $> script/send_pingback.rb http://site.com/page_linking_to_us.html http://my.rails.site.com/article-31

you can issue an XML-RPC pingback on the local server and debug things.

However, it should all work as it is shipped, so have fun when making your Rails site pingback’able!

Advertisements

3 thoughts on “Receiving Pingbacks on Rails sites

  1. I think I am missing something. I read the article a couple of times to see if I skipped some steps but that turned out to be not the case.

    The init.rb is not correct I think because nothing is loaded. There are no additional modules, helpers, controllers etc.

    Like

  2. i just started reading the spec for pingbacks (intending to write this), when after my excitement of a challenge subsided and i thought: “someone has probably already written this.”.

    alas, you have.

    thanks! (i guess i have more time now to work on other projects)
    😉

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s