Added v 0.4.0 snapshot.
[twitter4r-core.git] / lib / twitter / core.rb
blob46e046369e5b7cac995c365440b9294726b921d0
1 # The Twitter4R API provides a nicer Ruby object API to work with 
2 # instead of coding around the REST API.
4 # Module to encapsule the Twitter4R API.
5 module Twitter
6   # Mixin module for classes that need to have a constructor similar to
7   # Rails' models, where a <tt>Hash</tt> is provided to set attributes
8   # appropriately.
9   # 
10   # To define a class that uses this mixin, use the following code:
11   #  class FilmActor
12   #    include ClassUtilMixin
13   #  end
14   module ClassUtilMixin #:nodoc:
15     def self.included(base) #:nodoc:
16       base.send(:include, InstanceMethods)
17     end
18     
19     # Instance methods defined for <tt>Twitter::ModelMixin</tt> module.
20     module InstanceMethods #:nodoc:
21       # Constructor/initializer that takes a hash of parameters that 
22       # will initialize *members* or instance attributes to the 
23       # values given.  For example,
24       # 
25       #  class FilmActor
26       #    include Twitter::ClassUtilMixin
27       #    attr_accessor :name
28       #  end
29       #  
30       #  class Production
31       #    include Twitter::ClassUtilMixin
32       #    attr_accessor :title, :year, :actors
33       #  end
34       #  
35       #  # Favorite actress...
36       #  jodhi = FilmActor.new(:name => "Jodhi May")
37       #  jodhi.name # => "Jodhi May"
38       #  
39       #  # Favorite actor...
40       #  robert = FilmActor.new(:name => "Robert Lindsay")
41       #  robert.name # => "Robert Lindsay"
42       #  
43       #  # Jane is also an excellent pick...gotta love her accent!
44       #  jane = FilmActor.new(name => "Jane Horrocks")
45       #  jane.name # => "Jane Horrocks"
46       #  
47       #  # Witty BBC series...
48       #  mrs_pritchard = Production.new(:title => "The Amazing Mrs. Pritchard", 
49       #                                 :year => 2005, 
50       #                                 :actors => [jodhi, jane])
51       #  mrs_pritchard.title  # => "The Amazing Mrs. Pritchard"
52       #  mrs_pritchard.year   # => 2005
53       #  mrs_pritchard.actors # => [#<FilmActor:0xb79d6bbc @name="Jodhi May">, 
54       #  <FilmActor:0xb79d319c @name="Jane Horrocks">]
55       #  # Any Ros Pritchard's out there to save us from the Tony Blair
56       #  # and Gordon Brown *New Labour* debacle?  You've got my vote! 
57       #  
58       #  jericho = Production.new(:title => "Jericho", 
59       #                           :year => 2005, 
60       #                           :actors => [robert])
61       #  jericho.title   # => "Jericho"
62       #  jericho.year    # => 2005
63       #  jericho.actors  # => [#<FilmActor:0xc95d3eec @name="Robert Lindsay">]
64       # 
65       # Assuming class <tt>FilmActor</tt> includes 
66       # <tt>Twitter::ClassUtilMixin</tt> in the class definition 
67       # and has an attribute of <tt>name</tt>, then that instance 
68       # attribute will be set to "Jodhi May" for the <tt>actress</tt> 
69       # object during object initialization (aka construction for 
70       # you Java heads).
71       def initialize(params = {})
72         params.each do |key,val|
73           self.send("#{key}=", val) if self.respond_to? key
74         end
75         self.send(:init) if self.respond_to? :init
76       end
77       
78       protected
79         # Helper method to provide an easy and terse way to require 
80         # a block is provided to a method.
81         def require_block(block_given)
82           raise ArgumentError, "Must provide a block" unless block_given
83         end
84     end
85   end # ClassUtilMixin
86   
87   # Exception subclass raised when there is an error encountered upon 
88   # querying or posting to the remote Twitter REST API.
89   # 
90   # To consume and query any <tt>RESTError</tt> raised by Twitter4R:
91   #  begin
92   #    # Do something with your instance of <tt>Twitter::Client</tt>.
93   #    # Maybe something like:
94   #    timeline = twitter.timeline_for(:public)
95   #  rescue RESTError => re
96   #    puts re.code, re.message, re.uri
97   #  end
98   # Which on the code raising a <tt>RESTError</tt> will output something like:
99   #  404
100   #  Resource Not Found
101   #  /i_am_crap.json
102   class RESTError < RuntimeError 
103     include ClassUtilMixin
104     @@ATTRIBUTES = [:code, :message, :uri, :error]
105     attr_accessor :code, :message, :uri, :error
106     
107     # Returns string in following format:
108     #  "HTTP #{@code}: #{@message} at #{@uri}"
109     # For example,
110     #  "HTTP 404: Resource Not Found at /i_am_crap.json"
111     def to_s
112       "HTTP #{@code}: #{@message} at #{@uri}"
113     end
114   end # RESTError
115   
116   # Remote REST API interface representation
117   # 
118   class RESTInterfaceSpec
119         include ClassUtilMixin
120         
121   end
122   
123   # Remote REST API method representation
124   # 
125   class RESTMethodSpec
126         include ClassUtilMixin
127         attr_accessor :uri, :method, :parameters
128   end
129   
130   # Remote REST API method parameter representation
131   # 
132   class RESTParameterSpec
133         include ClassUtilMixin
134         attr_accessor :name, :type, :required
135         def required?; @required; end
136   end