The Open Data Protocol is gaining traction and is something to look at if you expose data over the web. .NET 4 has everything you need to build and consume OData with WCF Data Services. It's also easy to consume OData from outside of .NET - everything from JavaScript to Excel.
I've been working with Ruby against a couple OData services, and using Damien White's ruby_odata. Here is some ruby code to dump out the available courses in Pluralsight's OData feed.
require 'lib/ruby_odata' svc = OData::Service.new "http://www.pluralsight-training.net/Odata/" svc.Courses courses = svc.execute courses.each do |c| puts "#{c.Title}" end
ruby_odata builds types to consume the feed, and also maps OData query options.
svc.Courses.filter("substringof('Fundamentals', Title) eq true") fundamentals = svc.execute fundamentals.each do |c| puts "#{c.Title}" end
There is one catch - the Pluralsight model uses inheritance for a few of the entities:
<EntityType Name="ModelItemBase"> <Property Name="Title" Type="Edm.String" ...="" /> <!-- ... --> </EntityType> <EntityType Name="Course" BaseType="ModelItemBase"> <Property Name="Name" Type="Edm.String" Nullable="true" /> <!-- ... --> </EntityType>
Out of the box, ruby_odata doesn't handle the BaseType attribute and misses inherited properties, so I had to hack around in service.rb with some of the Nokogiri APIs that parse the service metadata (this code only handles a one level of inheritance, and gets invoked when building entity types):
def collect_properties(edm_ns, element, doc) props = element.xpath(".//edm:Property", "edm" => edm_ns) methods = props.collect { |p| p['Name'] } unless element["BaseType"].nil? base = element["BaseType"].split(".").last() baseType = doc.xpath("//edm:EntityType[@Name=\"#{base}\"]", "edm" => edm_ns).first() props = baseType.xpath(".//edm:Property", "edm" => edm_ns) methods = methods.concat(props.collect { |p| p['Name']}) end return methods end
The overall Ruby <-> OData experience has been quite good.