From de9b4fb6baf02ced03db8893f8d5161ac61c91d8 Mon Sep 17 00:00:00 2001 From: John Nunemaker Date: Sun, 27 Jul 2008 16:35:31 -0400 Subject: [PATCH] Put in first wave of parsing. Supports json and xml. --- examples/twitter.rb | 11 +++++--- lib/web.rb | 22 +++++++++++----- lib/web/entities.rb | 63 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 lib/web/entities.rb diff --git a/examples/twitter.rb b/examples/twitter.rb index d0a736d..ff4afdd 100644 --- a/examples/twitter.rb +++ b/examples/twitter.rb @@ -1,14 +1,17 @@ dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')) require File.join(dir, 'web') +require 'pp' config = YAML::load(File.read(File.join(ENV['HOME'], '.twitter'))) class Twitter include Web + base_uri 'twitter.com' + format :xml + + entity :status + entity :user end Twitter.basic_auth config['email'], config['password'] -puts Twitter.get('/statuses/user_timeline.json') - -# puts Twitter.post('/direct_messages/new.xml', :query => {:user => 'jnunemaker', :text => 'Hello from Web'}) -# puts Twitter.response.code \ No newline at end of file +pp Twitter.get('/statuses/user_timeline.xml', :entity => :status) \ No newline at end of file diff --git a/lib/web.rb b/lib/web.rb index e4686f1..a3d4566 100644 --- a/lib/web.rb +++ b/lib/web.rb @@ -1,15 +1,21 @@ require 'net/http' require 'net/https' require 'uri' +require 'ostruct' require 'rubygems' require 'active_support' $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) + +dir = File.expand_path(File.join(File.dirname(__FILE__), 'web')) +require dir + '/entities' + module Web def self.included(base) base.extend ClassMethods + base.send(:include, Web::Entities) end module ClassMethods @@ -73,8 +79,15 @@ module Web request.body = options[:body] unless options[:body].blank? request.initialize_http_header headers.merge(options[:headers] || {}) request.basic_auth(@auth[:username], @auth[:password]) if @auth - @response = http.start() { |conn| conn.request(request) } - @response.body + @response = http.start() { |conn| conn.request(request) } + + if !options[:entity] || options[:entity].blank? + @response.body + else + entity = @entities.detect { |e| e.name.to_s == options[:entity].to_s } + raise 'Entity not found' if entity.blank? + entity.parse(@response.body) + end end # Makes it so uri is sure to parse stuff like google.com with the http @@ -82,7 +95,4 @@ module Web str =~ /^https?:\/\// ? str : "http#{'s' if str.include?(':443')}://#{str}" end end -end - -dir = File.expand_path(File.join(File.dirname(__FILE__), 'web')) -require dir + '/entity' \ No newline at end of file +end \ No newline at end of file diff --git a/lib/web/entities.rb b/lib/web/entities.rb new file mode 100644 index 0000000..a2beabe --- /dev/null +++ b/lib/web/entities.rb @@ -0,0 +1,63 @@ +module Web + module Entities + def self.included(base) + base.extend ClassMethods + end + + module ClassMethods + def format(f) + return @format unless f + @format = f.to_s + end + + def entity(name, &block) + @entities ||= [] + entity = Entity.new(name) + yield(entity) if block_given? + if entity.format.blank? && !@format.blank? + entity.format = @format + end + @entities << entity + end + end + + class Entity + attr_accessor :name + + def initialize(name) + @name = name + end + + def format(f=nil) + return @format if f.blank? + self.format = f.to_s + end + + def format=(f) + raise 'Unsupported format' unless %w[xml json].include?(f.to_s) + @format = f.to_s + end + + def attributes(*names) + return @attributes if names.blank? + @attributes = names.flatten + end + + def has_one(*items) + @has_ones = items.flatten + end + + def parse(body) + send("from_#{format}", body) + end + + def from_xml(body) + Hash.from_xml(body) + end + + def from_json(json) + ActiveSupport::JSON.decode(json) + end + end + end +end \ No newline at end of file