Rails 2.0 Finally Released - What's New

Ruby on Rails is one of the most used frameworks for new web 2.0 startups. This 2.0 release is the second recent present that we web developers have recieved this Christmas (the first was OpenID 2.0). Since Rails 2.0 was recently released I wanted to write about the recent changes.

Below is a rundown of the changes write from the Ruby on Rails blog.

Action Pack: Resources

This is where the bulk of the action for 2.0 has gone. We’ve got a slew of improvements to the RESTful lifestyle. First, we’ve dropped the semicolon for custom methods instead of the regular slash. So /people/1;edit is now /people/1/edit. We’ve also added the namespace feature to routing resources that makes it really easy to confine things like admin interfaces:

map.namespace(:admin) do |admin|
  admin.resources :products,
    :collection => { :inventory => :get },
    :member     => { :duplicate => :post },
    :has_many   => [ :tags, :images, :variants ]

Which will give you named routes like inventory_admin_products_url and admin_product_tags_url. To keep track of this named routes proliferation, we’ve added the “rake routes” task, which will list all the named routes created by routes.rb.

We’ve also instigated a new convention that all resource-based controllers will be plural by default. This allows a single resource to be mapped in multiple contexts and still refer to the same controller. Example:

  # /avatars/45 => AvatarsController#show
  map.resources :avatars

  # /people/5/avatar => AvatarsController#show 
  map.resources :people, :has_one => :avatar

Action Pack: Multiview

Alongside the improvements for resources come improvements for multiview. We already have #respond_to, but we’ve taken it a step further and made it dig into the templates. We’ve separated the format of the template from its rendering engine. So show.rhtml now becomes show.html.erb, which is the template that’ll be rendered by default for a show action that has declared format.html in its respond_to. And you can now have something like show.csv.erb, which targets text/csv, but also uses the default ERB renderer.

So the new format for templates is action.format.renderer. A few examples:

  • show.erb: same show template for all formats
  • index.atom.builder: uses the Builder format, previously known as rxml, to render an index action for the application/atom+xml mime type
  • edit.iphone.haml: uses the custom HAML template engine (not included by default) to render an edit action for the custom Mime::IPHONE format

Speaking of the iPhone, we’ve made it easier to declare “fake” types that are only used for internal routing. Like when you want a special HTML interface just for an iPhone. All it takes is something like this:

# should go in config/initializers/mime_types.rb Mime.register_alias "text/html", :iphone class ApplicationController < ActionController::Base before_filter :adjust_format_for_iphone private def adjust_format_for_iphone if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(iPhone|iPod)/] request.format = :iphone end end end class PostsController < ApplicationController def index respond_to do |format| format.html # renders index.html.erb format.iphone # renders index.iphone.erb end end end

You’re encouraged to declare your own mime-type aliases in the config/initializers/mime_types.rb file. This file is included by default in all new applications.

Action Pack: Record identification

Piggy-backing off the new drive for resources are a number of simplifications for controller and view methods that deal with URLs. We’ve added a number of conventions for turning model classes into resource routes on the fly. Examples:

  # person is a Person object, which by convention will 
  # be mapped to person_url for lookup
  link_to(person.name, person)

Action Pack: HTTP Loving

As you might have gathered, Action Pack in Rails 2.0 is all about getting closer with HTTP and all its glory. Resources, multiple representations, but there’s more. We’ve added a new module to work with HTTP Basic Authentication, which turns out to be a great way to do API authentication over SSL. It’s terribly simple to use. Here’s an example (there are more in ActionController::HttpAuthentication):

class PostsController < ApplicationController USER_NAME, PASSWORD = "dhh", "secret" before_filter :authenticate, :except => [ :index ] def index render :text => "Everyone can see me!" end def edit render :text => "I'm only accessible if you know the password" end private def authenticate authenticate_or_request_with_http_basic do |user_name, password| user_name == USER_NAME && password == PASSWORD end end end

We’ve also made it much easier to structure your JavaScript and stylesheet files in logical units without getting clobbered by the HTTP overhead of requesting a bazillion files. Using javascript_include_tag(:all, :cache => true) will turn public/javascripts/.js into a single public/javascripts/all.js file in production, while still keeping the files separate in development, so you can work iteratively without clearing the cache.

Along the same lines, we’ve added the option to cheat browsers who don’t feel like pipelining requests on their own. If you set ActionController::Base.asset_host = “assets%d.example.com”, we’ll automatically distribute your asset calls (like image_tag) to asset1 through asset4. That allows the browser to open many more connections at a time and increases the perceived speed of your application.

Action Pack: Security

Making it even easier to create secure applications out of the box is always a pleasure and with Rails 2.0 we’re doing it from a number of fronts. Most importantly, we now ship we a built-in mechanism for dealing with CRSF attacks. By including a special token in all forms and Ajax requests, you can guard from having requests made from outside of your application. All this is turned on by default in new Rails 2.0 applications and you can very easily turn it on in your existing applications using ActionController::Base.protect_from_forgery (see ActionController::RequestForgeryProtection for more).

We’ve also made it easier to deal with XSS attacks while still allowing users to embed HTML in your pages. The old TextHelper#sanitize method has gone from a black list (very hard to keep secure) approach to a white list approach. If you’re already using sanitize, you’ll automatically be granted better protection. You can tweak the tags that are allowed by default with sanitize as well. See TextHelper#sanitize for details.

Finally, we’ve added support for HTTP only cookies. They are not yet supported by all browsers, but you can use them where they are.

Action Pack: Exception handling

Lots of common exceptions would do better to be rescued at a shared level rather than per action. This has always been possible by overwriting rescue_action_in_public, but then you had to roll out your own case statement and call super. Bah. So now we have a class level macro called rescue_from, which you can use to declaratively point certain exceptions to a given action. Example:

  class PostsController < ApplicationController
    rescue_from User::NotAuthorized, :with => :deny_access

      def deny_access

Action Pack: Cookie store sessions

The default session store in Rails 2.0 is now a cookie-based one. That means sessions are no longer stored on the file system or in the database, but kept by the client in a hashed form that can’t be forged. This makes it not only a lot faster than traditional session stores, but also makes it zero maintenance. There’s no cron job needed to clear out the sessions and your server won’t crash because you forgot and suddenly had 500K files in tmp/session.

This setup works great if you follow best practices and keep session usage to a minimum, such as the common case of just storing a user_id and a the flash. If, however, you are planning on storing the nuclear launch codes in the session, the default cookie store is a bad deal. While they can’t be forged (so is_admin = true is fine), their content can be seen. If that’s a problem for your application, you can always just switch back to one of the traditional session stores (but first investigate that requirement as a code smell).

Action Pack: New request profiler

Figuring out where your bottlenecks are with real usage can be tough, but we just made it a whole lot easier with the new request profiler that can follow an entire usage script and report on the aggregate findings. You use it like this:

$ cat login_session.rb get_with_redirect '/' say "GET / => #{path}" post_with_redirect '/sessions', :username => 'john', :password => 'doe' say "POST /sessions => #{path}" $ ./script/performance/request -n 10 login_session.rb

And you get a thorough breakdown in HTML and text on where time was spent and you’ll have a good idea on where to look for speeding up the application.

Action Pack: Miscellaneous

Also of note is AtomFeedHelper, which makes it even simpler to create Atom feeds using an enhanced Builder syntax. Simple example:

  # index.atom.builder:
  atom_feed do |feed|
    feed.title("My great blog!")

    for post in @posts
      feed.entry(post) do |entry|
        entry.content(post.body, :type => 'html')

        entry.author do |author|

We’ve made a number of performance improvements, so asset tag calls are now much cheaper and we’re caching simple named routes, making them much faster too.

Finally, we’ve kicked out in_place_editor and autocomplete_for into plugins that live on the official Rails SVN.

Active Record: Performance

Active Record has seen a gazillion fixes and small tweaks, but it’s somewhat light on big new features. Something new that we have added, though, is a very simple Query Cache, which will recognize similar SQL calls from within the same request and return the cached result. This is especially nice for N+1 situations that might be hard to handle with :include or other mechanisms. We’ve also drastically improved the performance of fixtures, which makes most test suites based on normal fixture use be 50-100% faster.

Active Record: Sexy migrations

There’s a new alternative format for declaring migrations in a slightly more efficient format. Before you’d write:

create_table :people do |t|
  t.column, "account_id",  :integer
  t.column, "first_name",  :string, :null => false
  t.column, "last_name",   :string, :null => false
  t.column, "description", :text
  t.column, "created_at",  :datetime
  t.column, "updated_at",  :datetime

Now you can write:

create_table :people do |t|
  t.integer :account_id
  t.string  :first_name, :last_name, :null => false
  t.text    :description

Active Record: Foxy fixtures

The fixtures in Active Record has taken a fair amount of flak lately. One of the key points in that criticism has been the work with declaring dependencies between fixtures. Having to relate fixtures through the ids of their primary keys is no fun. That’s been addressed now and you can write fixtures like this:

  # sellers.yml
    name: Shopify

  # products.yml
    seller: shopify
    name: Pimp cup

As you can see, it’s no longer necessary to declare the ids of the fixtures and instead of using seller_id to refer to the relationship, you just use seller and the name of the fixture.

Active Record: XML in, JSON out

Active Record has supported serialization to XML for a while. In 2.0 we’ve added deserialization too, so you can say Person.new.from_xml(“
David“) and get what you’d expect. We’ve also added serialization to JSON, which supports the same syntax as XML serialization (including nested associations). Just do person.to_json and you’re ready to roll.

Active Record: Shedding some weight

To make Active Record a little leaner and meaner, we’ve removed the acts_as_XYZ features and put them into individual plugins on the Rails SVN repository. So say you’re using acts_as_list, you just need to do ./script/plugin install acts_as_list and everything will move along like nothing ever happened.

A little more drastic, we’ve also pushed all the commercial database adapters into their own gems. So Rails now only ships with adapters for MySQL, SQLite, and PostgreSQL. These are the databases that we have easy and willing access to test on. But that doesn’t mean the commercial databases are left out in the cold. Rather, they’ve now been set free to have an independent release schedule from the main Rails distribution. And that’s probably a good thing as the commercial databases tend to require a lot more exceptions and hoop jumping on a regular basis to work well.

The commercial database adapters now live in gems that all follow the same naming convention: activerecord-XYZ-adapter. So if you gem install activerecord-oracle-adapter, you’ll instantly have Oracle available as an adapter choice in all the Rails applications on that machine. You won’t have to change a single line in your applications to take use of it.

That also means it’ll be easier for new database adapters to gain traction in the Rails world. As long as you package your adapter according to the published conventions, users just have to install the gem and they’re ready to roll.

Active Record: with_scope with a dash of syntactic vinegar

ActiveRecord::Base.with_scope has gone protected to discourage people from misusing it in controllers (especially in filters). Instead, it’s now encouraged that you only use it within the model itself. That’s what it was designed for and where it logically remains a good fit. But of course, this is all about encouraging and discouraging. If you’ve weighed the pros and the cons and still want to use with_scope outside of the model, you can always call it through .send(:with_scope).

ActionWebService out, ActiveResource in

It’ll probably come as no surprise that Rails has picked a side in the SOAP vs REST debate. Unless you absolutely have to use SOAP for integration purposes, we strongly discourage you from doing so. As a naturally extension of that, we’ve pulled ActionWebService from the default bundle. It’s only a gem install actionwebservice away, but it sends an important message none the less.

At the same time, we’ve pulled the new ActiveResource framework out of beta and into the default bundle. ActiveResource is like ActiveRecord, but for resources. It follows a similar API and is configured to Just Work with Rails applications using the resource-driven approach. For example, a vanilla scaffold will be accessible by ActiveResource.


There’s not all that much new in ActiveSupport. We’ve a host of new methods like Array#rand for getting a random element from an array, Hash#except to filter down a hash from undesired keys and lots of extensions for Date. We also made testing a little nicer with assert_difference. Short of that, it’s pretty much just fixes and tweaks.

Action Mailer

This is a very modest update for Action Mailer. Besides a handful of bug fixes, we’ve added the option to register alternative template engines and assert_emails to the testing suite, which works like this:

  1. Assert number of emails delivered within a block:
    assert_emails 1 do
    post :signup, :name => ‘Jonathan’


Rails: The debugger is back

To tie it all together, we have a stream of improvements for Rails in general. My favorite amongst these is the return of the breakpoint in form of the debugger. It’s a real debugger too, not just an IRB dump. You can step back and forth, list your current position, and much more. It’s all coming from the gracious note of the ruby-debug gem. So you’ll have to install that for the new debugger to work.

To use the debugger, you just install the gem, put “debugger” somewhere in your application, and then start the server with—debugger or -u. When the code executes the debugger command, you’ll have it available straight in the terminal running the server. No need for script/breakpointer or anything else. You can use the debugger in your tests too.

Rails: Clean up your environment

Before Rails 2.0, config/environment.rb files every where would be clogged with all sorts of one-off configuration details. Now you can gather those elements in self-contained files and put them under config/initializers and they’ll automatically be loaded. New Rails 2.0 applications ship with two examples in form of inflections.rb (for your own pluralization rules) and mime_types.rb (for your own mime types). This should ensure that you need to keep nothing but the default in config/environment.rb.

Rails: Easier plugin order

Now that we’ve yanked out a fair amount of stuff from Rails and into plugins, you might well have other plugins that depend on this functionality. This can require that you load, say, acts_as_list before your own acts_as_extra_cool_list plugin in order for the latter to extend the former.

Before, this required that you named all your plugins in config.plugins. Major hassle when all you wanted to say was “I only care about acts_as_list being loaded before everything else”. Now you can do exactly that with config.plugins = [ :acts_as_list, :all ].

And hundreds upon hundreds of other improvements

What I’ve talked about above is but a tiny sliver of the full 2.0 package. We’ve got literally hundreds of bug fixes, tweaks, and feature enhancements crammed into Rails 2.0. All this coming off the work of tons of eager contributors working tirelessly to improve the framework in small, but important ways.

I encourage you to scourger the CHANGELOGs and learn more about all that changed.

Click here to read the full post on the Ruby on Rails blog.

There are a lot of big changes here that should be useful when developing using Rails. One of my personal favorites is the ability to change XML into JSON, which being someone that likes JSON could come in handy (especially if you are getting data from a web service that is using XML and your application needs to use JSON). I look forward to seeing what new applications will be built on Rails 2.0.

Special thanks to thegreatone who submitted the Rails 2.0 post from the Ruby on Rails blog on Social Ajaxonomy.
Click here to see the post on Social Ajaxonomy

If you would like to submit a post for chance to have us blog about it click here to go to Social Ajaxonomy or click on the "Social" link located at the top link navigation of Ajaxonomy.


Convert RSS to JSON


John Resig has written another great coding example. The code takes an RSS Feed and converts it into JSON. You will also notice that in the code he uses DOM manipulation instead of eval (you can read my post on using JSON without eval by clicking here) to bring the code into the JavaScript.

Below is an excerpt from the post.


This script currently has a REST interface, accessible via a GET request. The full request would look something like this:
GET http://ejohn.org/apps/rss2json/?url=URL&callback=CALLBACK
the URL parameter would contain the URL of the RSS/Atom feed which you are attempting to convert. The optional Callback parameter would reference a callback function that you wish to have called, with the new data.

You can test this out by visiting the following URL:
Sample Code and Demo

A simple, sample, program would look something like this:
getRSS("http://digg.com/rss/index.xml", handleRSS);

function handleRSS(rss) {
alert( "Dowloaded: " + rss.title );

function getRSS(url, callback) {
feedLoaded = callback;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "http://ejohn.org/apps/rss2json/?url=" + url
+ "&callback=feedLoaded&t=" + (new Date()).getTime();

Click here to read the full post. The post also contains the back end code as well as the above.

This idea could be used for any XML web service that you would like to have in JSON. So, if you have an application that uses JSON and the data you need is in XML try extending this code to meet your needs.

Ajaxonomy.com Launches Social Network


Ajaxonomy.com is proud to present it's latest addition, Social Ajaxonomy, a social network for developers to share links in a digg-style environment.

This is where the community can submit links to articles, sites, posts, and whatever else it finds pertaining to Ajax and other interesting web technologies and further provides users with an opportunity to vote on which links they find useful and valuable. Top articles have a chance to appear in the main blog. So, we hope that you would register an account, build a profile, and start submitting and voting for links! We look forward to growing in this community with you.

Please post your comments!

Facebook Application Development with CakePHP


Facebook is one of the largest social networks and has become a great platform to develop for. I have found a good tutorial on developing an application from Facebook Developer (click here to read the original tutorial)

Below are the steps for the tutorial.

Step 1. The first step is to create a . In setting up, only a few of the settings are vital for getting started.

* Include an application name of your preference.
* Within the “Optional Fields” section, provide the callback URL where you intend to host the application. The callback URL should point to the root path of your CakePHP installation.
* Enter a Canvas Page URL that has not already been taken, and make sure FBML is selected.
* If you do not want friends or other random users installing your application yet, make sure to check off the Developer Mode box.
* Lastly, set the Side Nav URL to the same value as the Canvas Page URL.

Step 2. Now that your application is set up, you’ll need to download and unzip the latest stable version of CakePHP.

Step 3. Create a new folder within your CakePHP application under “/app/vendor/facebook”. Download the latest version of the Facebook Platform API, and unzip the contents of the “client” folder into the new “facebook” folder created a moment ago. (PHP4 users should unzip the contents of the “php4client” folder instead.) You should now have the directory contents as follows.

* /app/vendors/facebook/facebook.php
* /app/vendors/facebook/facebook_desktop.php
* /app/vendors/facebook/facebookapi_php5_restlib.php

Step 4. You’ll now need to modify the AppController base class such that all your inherited controllers utilize the Facebook API. To start, copy app_controller.php from “/cake” to “/app”. Next, open the file up in your preferred text editor, and change its contents to match the following. (Make sure you change the values for the Facebook API key and secret in the process.)
view plaincopy to clipboardprint?


class AppController extends Controller {
var $facebook;

var $__fbApiKey = 'YOUR_API_KEY';
var $__fbSecret = 'YOUR_SECRET_KEY';

function __construct() {

// Prevent the 'Undefined index: facebook_config' notice from being thrown.
$GLOBALS['facebook_config']['debug'] = NULL;

// Create a Facebook client API object.
$this->facebook = new Facebook($this->__fbApiKey, $this->__fbSecret);

Step 5. Create a basic controller class that inherits the AppController defined above. Here we’ll perform basic Facebook calls such as logging in. Additionally, an example view named “index” is included, representing the index page of the things controller.
view plaincopy to clipboardprint?

class ThingsController extends AppController {
var $user;

* Name: beforeFilter
* Desc: Performs necessary steps and function calls prior to executing
* any view function calls.
function beforeFilter() {
$this->user = $this->facebook->require_login();

* Name: index
* Desc: Display the friends index page.
function index() {
// Retrieve the user's friends and pass them to the view.
$friends = $this->facebook->api_client->friends_get();
$this->set('friends', $friends);

Step 6. Create a placeholder model object under “/app/model” named thing.php. Again, place the following contents into the new file.
view plaincopy to clipboardprint?

class Thing extends AppModel {
var $name = 'Thing';
var $useTable = false;

Step 7. In order to ensure consistency between pages, you’ll want to create a default layout. This is a place to include header and footer FBML. Create a new document in your text editor named “/app/views/layouts/default.thtml”, and insert some code such as the following. The vital part that must be included is the echo call to print the $content_for_layout variable.
view plaincopy to clipboardprint?

<fb:google-analytics uacct="YOUR-GOOGLE-ID"/>

<style type="text/css">
.container { padding:10px; }

<fb:action href="things">My Things
<fb:action href="things/browse">Browse Things
<fb:action href="things/search">Search Things
<fb:create-button href="things/add">Add Things

<div class="container"><?php echo $content_for_layout;?></div>

Step 8. Finally, you need to create a file that represents the layout of the index view defined as a function of ThingsController from step 5. Create a new file named “/app/views/things/index.thtml”, and insert the below contents. Note the use of the $friends variable, which was passed from the index function via a call to the controller’s set function.
view plaincopy to clipboardprint?

<p><b>My Things</b></p>
<p>My Friends:</p>
<?php foreach ($friends as $friend):?>
<li><?php echo $friend;?></li>
<?php endforeach;?>

Step 9. The last step is to upload your cake application to your server (making sure to match the callback URL path set for your application). You can now access the page via: http://apps.facebook.com/YOUR-APP-PATH/things.

Now that you have an easy tutorial I would love to hear about any good projects that you have created for Facebook (perhaps we should make an Ajaxonomy Facebook application and of course blog about the development). You can put them in the comments or if they are blogged about put them in social for a chance to have an article written in the main Ajaxonomy blog.

Simple "Class" Instantiation in Javascript


John Resig has pulled out his bag-o-tricks and shared another golden nugget with us.

This time he shares a pattern to simplify Class-style instantiation of a function in JavaScript.

In a nutshell, John takes this example:

function User(first, last){
    this.name = first + " " + last;

var user = new User("John", "Resig");

and shows how it can become a debugging nightmare and why it's not as efficient and flexible as other methods. Most importantly, he covers why the use of "this" in a function requires that it be instantiated and not called directly.

Then, he gives us the solution that solves the problems raised in the code above with this example:

function User(first, last){
  if ( this instanceof User ) {
    this.name = first + " " + last;
  } else
    return new User(first, last);

Then he wraps this together into a generic class constructor that can be reused to build these types of functions:

// makeClass - By John Resig (MIT Licensed)
function makeClass(){
  return function(args){
    if ( this instanceof arguments.callee ) {
      if ( typeof this.init == "function" )
        this.init.apply( this, args );
    } else
      return new arguments.callee( arguments );

Refactoring the original example code at the top of this post with this generic class constructor would produce:

var User = makeClass();
User.prototype.init = function(first, last){
  this.name = first + " " + last;
var user = User("John", "Resig");
// => "John Resig" 

Click here to read John's post in which he does a great job explaining the code above (including the pitfalls of the original example and how the solution works).

DOJO accepted DWR as its sponsored project

This is a follow-up to my original article:

Today DOJO Foundation members voted 10-2 (10-yes, 2-no) in favor of DWR as a sponsored project. It means, DWR is officially part of DOJO foundation now.

Google Developer Podcast: Android


Dick Wall, of Google Developer Programs, has posted a podcast in which two architects on the Android engineering team talk about the Android platform from a technical perspective.

Other topics in the podcast include:

  • Some history behind the project
  • The high level architecture of Android. For example, how Linux processes handle the VM and manage security (the VM doesn't handle it)
  • Details on the Dalvik VM and how it is optimized for small devices
  • The architecture: From Intents to Views to Permissions and more
  • How XML is slow, but the tools convert the XML to a nicer format for you
  • The tooling and steps for building an application on Android
  • How so many objects have a URL, and how the environment is like a mini-SOA (Services across processes instead of across the network)
  • Thoughts on how you program for small devices, and things to watch out for if you move from the desktop
  • The control, or lack of control that you have over the application lifecycle
  • "Everything you do drains the battery"
  • The thread story: they exist, you don't have to deal with them if you don't want to, and the UI
  • Using XMPP for messaging

You can download the episode directly, or subscribe to the show (click here for iTunes one-click subscribe).

Click here to visit the Android Developer Blog

OpenID 2.0 Finally Released!


It is Christmas time and we web developers have just received a great gift. OpenID 2.0 has finally been released. This will hopefully allow for greater adoption of the API (especially now that both Microsoft and Google have announced their supporting of it).

Below is from the OpenID site.

While its certainly been a long process in the making, we’re now quite excited to announce OpenID Authentication 2.0 and OpenID Attribute Exchange 1.0 as final specifications (”OpenID 2.0?). This morning was the closing day of the Internet Identity Workshop and David Recordon, Dick Hardt, and Josh Hoyt (three of the authors and editors) made the announcement during the first session. Both specifications have evolved through extensive community participation and feedback and each have been stable for a number of months. There are already a variety of open source libraries shipping these specifications with product support including Google’s Blogger (via Sxip’s library) and Drupal who did their own implementation of the specifications. Multiple OpenID Providers including MyOpenID, Sxipper, and VeriSign’s PIP already have support for both of these specifications. Given past trends, growing support of OpenID 2.0 should be no different.

Click here to read the full post.

I can't wait to see what new applications are made using the OpenID 2.0.

Thanks to Macskeeball for letting us know of this news. If you would like to let us know of upcoming news you can now use our new social feature (you'll be hearing more about this soon) that will allow for you to let us know what you would like on the blog.

Making Money With Your Open Source Project

So you've just finished the best open source project since Linux and your are very happy with the results. Now that you have put all that sweat and tears into your project your pocketbook is still empty (even after 100,000 installs of your project). How do you capitalizing on your project, so that you can continue to improve the project (with the help of the open source community of course).

SorceForge.net now offers a service where you can sell support of your project, so that you can keep users happy and make a little money as well. The service is modeled on eBay's marketplace and will compete with Red Hat's Exchange launched earlier this year. The advantage that SourceForge.net has is that most open source projects are already posted on the service so many people will already be using the service to get download the project. There are already more than 800 listings and the number is expected to explode very quickly.

It is always good to see something like this that helps keep open source projects going.

Click here to go to the market place.


Digg Changes and API Tutorial

If you have been using the social network Digg, you have noticed that there are a number of changes. A large portion of the changes involve images and they are working with Photobucket to make may of these changes.

The big changes are described by Kevin Rose on the Digg blog.

* New Universal Taxonomy
Now you can submit news, images, or videos to any category on Digg! Categories will be consistent across the board, which means you can view all media types in a given topic, or view one media type at a time (e.g., only images under the “sports” category). We’re also excited to support the launch with new categories. “Offbeat” will be its own category, with new topics, and we’re adding a whole new “Lifestyle” category with topics like Autos, Food & Drink, and Travel. As always, if you don’t want to see a particular topic or media type on Digg, you can click the customize button in the navigation to filter your view.
* New Images Crawler
Submitting images to Digg is basically the same as submitting news and videos, with a few notable differences. When you submit a link to a web page containing multiple images, Digg will crawl the page and present up to ten image thumbnails from that page for you to choose the one you want. We’ve also added this technology to news submissions.
* Sorting and Duplicate Image Detection
We’ve added a new sort to the images section called “mosaic” view – it’s great for browsing image thumbnails. To help prevent people from submitting duplicate images, we’ve added image recognition technology from Idée Inc.

Also, on the post is that Photobucket used the Digg API to build a Digg channel. After hearing this it got me looking for a good tutorial for using the Digg API. I found a great article on using the Digg API with Ruby on Rails. Of course Rails is a great framework used by many Web 2.0 companies so this may be a useful tutorial.

Below is an excerpt from the post (click here to read the full post).

This tutorial will cover grabbing your most recent submitted articles and displaying the title and number of diggs in a list. With this code you can easily expand to grab any data you wish using the Digg API.

In your template you will need to make the following includes:

require 'open-uri'
require 'rexml/document'

open-uri will be used to grab the data from Digg and rexml will be used to parse the obtained xml data.

The next issue is to grab the data you need. In this case, I will grab the last 20 articles I have submitted ( a complete list of data to be grabbed is here.):

response = open("http://services.digg.com/user/[username]/submissions?appkey=http%3A%2F%2Fthembid.com&type=xml&count=20","User-Agent" => "Demo/0.1").read 

I split the above to three lines, because of the formatting, it should be one line. At the end of this post is a link to a text file with the proper formatting.


is your digg username.


is described here.


can be XML, JSON, javascript or PHP. Details are here.


determines how many data entries are retrieved. You can read more about arguments (like count) here.

Now that you have the XML stored in the response variable it’s time to use Ruby’s built in XML parser to grab the data you need.

Note that you can put the URI in the open function in your browser to see the full schema of the returned XML and make sure the data you want is retrieved.

The following code creates a new REXML object:

doc = REXML::Document.new(response)

Now lets grab the title (this is an example of retrieving a tag value):

titles = []
doc.elements.each("stories/story/title") { |element|
  titles << element.text

Now lets grab the number of diggs (this is an example of retrieving an attribute):

diggs = []
doc.elements.each("stories/story") { |element|
  diggs << element.attributes["diggs"]

Let’s now print out our title and number of diggs in a list:

<% count = 0
      while count < 20 
      <%= titles[count] %> (Diggs: <%= diggs[count] %>)
      count += 1

That’s it! With these simple instructions you can get, store and display all the data you need to create your next killer Digg API application in Ruby on Rails.

To get the tutorial code in a text file go to the original post by clicking here. It is good to see Digg continue to improve the service and soon they should be adding OpenID support (so it should be look Mom no password). Even though Digg sometimes has things not working properly it is good to see a network continue to change and improve.

Please leave your thoughts on the latest changes on Digg or your experience with the tutorial in the comments.

Syndicate content