<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,7 @@
+== 0.1.6 (2009-10-29)
+* Added support for HTTP methods beside GET and POST using block syntax
+* Added method for appending to the request path something that's not a valid ruby method
+
 == 0.1.5 (2009-10-28)
 Added support for the Twitter version 1 API as a API symbol :v1
 </diff>
      <filename>CHANGELOG.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -79,6 +79,20 @@ You can force a format. To update the authenticated user's status using the XML
 
 Or, with JSON
   client.statuses.update.json! :status=&gt;'this status is from grackle' #POST to http://twitter.com/statuses/update.json
+  
+===Using Other HTTP Verbs
+To use HTTP verbs like DELETE or PUT, Grackle provides a slightly different syntax:
+  client.put{ hayesdavis.lists.my_list :name=&gt;'New Name' } #HTTP PUT
+  client.delete{ direct_messages.destroy :id=&gt;1 } #HTTP DELETE
+  
+You may specify any method chain you wish in the block. Note that if your method chain inside the block 
+ends in a ! or ?, that the HTTP verb for the block will still be used. This means that
+  client.delete{ direct_messages.destroy! :id=&gt;1 } #Uses HTTP DELETE, not POST
+  client.direct_messages.destroy! :id=&gt;1 #Uses HTTP POST
+
+If for some reason you don't like the preferred block syntax above, you may specify a 
+parameter to your method chain called :__method (note the double underscores) to specify the HTTP verb:
+  client.direct_messages.destroy! :id=&gt;1, :__method=&gt;:delete #HTTP DELETE
 
 ===Toggling APIs
 By default, the Grackle::Client sends all requests to the unversioned Twitter REST API. If you want to send requests to 
@@ -125,6 +139,12 @@ the raw response body. The Grackle::Client has a default_format you can specify.
 If you don't include a named format in your method chain as described above, but use a &quot;?&quot; or &quot;!&quot; then the 
 Grackle::Client.default_format is used.
 
+===Odds and Ends
+If you need to append something to the request path that isn't a valid ruby method, e.g.
+  /1user/lists.json #1user isn't a valid Ruby method
+you can use the Grackle::Client#_ method like so:
+  client._('1user').lists.json
+
 == REQUIREMENTS:
 
 You'll need the following gems to use all features of Grackle:</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -2,11 +2,11 @@
 
 Gem::Specification.new do |s|
   s.name = %q{grackle}
-  s.version = &quot;0.1.5&quot;
+  s.version = &quot;0.1.6&quot;
 
   s.required_rubygems_version = Gem::Requirement.new(&quot;&gt;= 0&quot;) if s.respond_to? :required_rubygems_version=
   s.authors = [&quot;Hayes Davis&quot;]
-  s.date = %q{2009-05-23}
+  s.date = %q{2009-10-29}
   s.description = %q{Grackle is a lightweight library for the Twitter REST and Search API.}
   s.email = %q{hayes@appozite.com}
   s.files = [&quot;CHANGELOG.rdoc&quot;, &quot;README.rdoc&quot;, &quot;grackle.gemspec&quot;, &quot;lib/grackle.rb&quot;, &quot;lib/grackle/client.rb&quot;, &quot;lib/grackle/handlers.rb&quot;, &quot;lib/grackle/transport.rb&quot;, &quot;lib/grackle/utils.rb&quot;, &quot;test/test_grackle.rb&quot;, &quot;test/test_helper.rb&quot;, &quot;test/test_client.rb&quot;, &quot;test/test_handlers.rb&quot;]</diff>
      <filename>grackle.gemspec</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module Grackle
 
   # :stopdoc:
-  VERSION = '0.1.5'
+  VERSION = '0.1.6'
   LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
   PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
   # :startdoc:</diff>
      <filename>lib/grackle.rb</filename>
    </modified>
    <modified>
      <diff>@@ -45,13 +45,12 @@ module Grackle
   class Client
     
     class Request #:nodoc:
-      attr_accessor :client, :path, :method, :api, :ssl
+      attr_accessor :client, :path, :method, :api, :ssl, :params
       
       def initialize(client,api=:rest,ssl=true)
         self.client = client
         self.api = api
         self.ssl = ssl
-        self.method = :get
         self.path = ''
       end
       
@@ -74,9 +73,12 @@ module Grackle
       def scheme
         ssl ? 'https' :'http'
       end
+      
+      def params
+        @params ||= {}
+      end
     end
     
-    VALID_METHODS = [:get,:post,:put,:delete]
     VALID_FORMATS = [:json,:xml,:atom,:rss]
 
     # Contains the mapping of API name symbols to actual host (and path) 
@@ -133,26 +135,11 @@ module Grackle
       end
     end
                
-    def method_missing(name,*args)
-      #If method is a format name, execute using that format
-      if format_invocation?(name)
-        return call_with_format(name,*args)
-      end
-      #If method ends in ! or ? use that to determine post or get
-      if name.to_s =~ /^(.*)(!|\?)$/
-        name = $1.to_sym
-        #! is a post, ? is a get
-        self.request.method = ($2 == '!' ? :post : :get)          
-        if format_invocation?(name)
-          return call_with_format(name,*args)
-        else
-          self.request &lt;&lt; &quot;/#{$1}&quot;
-          return call_with_format(self.default_format,*args)
-        end
+    def method_missing(name,*args,&amp;block)
+      if block_given?
+        return request_with_http_method_block(name,&amp;block)
       end
-      #Else add to the request path
-      self.request &lt;&lt; &quot;/#{name}&quot;
-      self
+      append(name,*args)
     end
     
     # Used to toggle APIs for a particular request without setting the Client's default API
@@ -197,21 +184,53 @@ module Grackle
       auth[:password] = value
     end
     
+    def append(name,*args)
+      name = name.to_sym
+      #The args will be a hash, store them if they're specified
+      self.request.params = *args
+      #If method is a format name, execute using that format
+      if format_invocation?(name)
+        return call_with_format(name)
+      end
+      #If method ends in ! or ? use that to determine post or get
+      if name.to_s =~ /^(.*)(!|\?)$/
+        name = $1.to_sym
+        #! is a post, ? is a get - only set this if the method hasn't been set
+        self.request.method ||= ($2 == '!' ? :post : :get)          
+        if format_invocation?(name)
+          return call_with_format(name)
+        else
+          self.request &lt;&lt; &quot;/#{$1}&quot;
+          return call_with_format(self.default_format)
+        end
+      end
+      #Else add to the request path
+      self.request &lt;&lt; &quot;/#{name}&quot;
+      self
+    end
+    
+    alias_method :_, :append
+    
     protected
-      def call_with_format(format,params={})
-        id = params.delete(:id)
+      def call_with_format(format)
+        id = request.params.delete(:id)
         request &lt;&lt; &quot;/#{id}&quot; if id
         request &lt;&lt; &quot;.#{format}&quot;
-        res = send_request(params)
+        res = send_request
         process_response(format,res)
       ensure
         clear
       end
       
-      def send_request(params)
+      def send_request
         begin
+          http_method = (
+            request.params.delete(:__method) or request.method or :get
+          )
           transport.request(
-            request.method,request.url,:auth=&gt;auth,:headers=&gt;headers,:params=&gt;params, :timeout =&gt; timeout
+            http_method, request.url,
+            :auth=&gt;auth,:headers=&gt;headers,
+            :params=&gt;request.params,:timeout =&gt; timeout
           )
         rescue =&gt; e
           puts e
@@ -251,5 +270,19 @@ module Grackle
       def format_invocation?(name)
         self.request.path? &amp;&amp; VALID_FORMATS.include?(name)
       end
+      
+      def pending_request?
+        !@request.nil?
+      end
+
+      def request_with_http_method_block(method,&amp;block)
+        request.method = method
+        response = instance_eval(&amp;block)
+        if pending_request?
+          call_with_format(self.default_format)
+        else
+          response
+        end
+      end
   end
 end
\ No newline at end of file</diff>
      <filename>lib/grackle/client.rb</filename>
    </modified>
    <modified>
      <diff>@@ -19,12 +19,7 @@ module Grackle
     DEFAULT_REDIRECT_LIMIT = 5
     
     def req_class(method)
-      case method
-        when :get then Net::HTTP::Get
-        when :post then Net::HTTP::Post
-        when :put then Net::HTTP::Put
-        when :delete then Net::HTTP::Delete
-      end
+      Net::HTTP.const_get(method.to_s.capitalize)
     end
     
     # Options are one of</diff>
      <filename>lib/grackle/transport.rb</filename>
    </modified>
    <modified>
      <diff>@@ -195,6 +195,45 @@ class TestClient &lt; Test::Unit::TestCase
     client.statuses.public_timeline? :since=&gt;time  
     assert_equal(&quot;/statuses/public_timeline.json?since=#{CGI::escape(time.httpdate)}&quot;,Net::HTTP.request.path)
   end
+
+  def test_simple_http_method_block
+    client = new_client(200,'[{&quot;id&quot;:1,&quot;text&quot;:&quot;test 1&quot;}]')
+    client.delete { direct_messages.destroy :id=&gt;1, :other=&gt;'value' }
+    assert_equal(:delete,client.transport.method, &quot;delete block should use delete method&quot;)
+    assert_equal(&quot;/direct_messages/destroy/1.json&quot;,Net::HTTP.request.path)
+    assert_equal('value',client.transport.options[:params][:other])
+    
+    client = new_client(200,'{&quot;id&quot;:54321,&quot;screen_name&quot;:&quot;test_user&quot;}')
+    value = client.get { users.show.json? :screen_name=&gt;'test_user' }
+    assert_equal(:get,client.transport.method)
+    assert_equal('http',client.transport.url.scheme)
+    assert(!Net::HTTP.last_instance.use_ssl?,'Net::HTTP instance should not be set to use SSL')
+    assert_equal('twitter.com',client.transport.url.host)
+    assert_equal('/users/show.json',client.transport.url.path)
+    assert_equal('test_user',client.transport.options[:params][:screen_name])
+    assert_equal('screen_name=test_user',Net::HTTP.request.path.split(/\?/)[1])
+    assert_equal(54321,value.id)    
+  end
+  
+  def test_http_method_blocks_choose_right_method
+    client = new_client(200,'[{&quot;id&quot;:1,&quot;text&quot;:&quot;test 1&quot;}]')
+    client.get { search :q=&gt;'test' }
+    assert_equal(:get,client.transport.method, &quot;Get block should choose get method&quot;)
+    client.delete { direct_messages.destroy :id=&gt;1 }
+    assert_equal(:delete,client.transport.method, &quot;Delete block should choose delete method&quot;)
+    client.post { direct_messages.destroy :id=&gt;1 }
+    assert_equal(:post,client.transport.method, &quot;Post block should choose post method&quot;)
+    client.put { direct_messages :id=&gt;1 }
+    assert_equal(:put,client.transport.method, &quot;Put block should choose put method&quot;)
+  end
+  
+  def test_http_method_selection_precedence
+    client = new_client(200,'[{&quot;id&quot;:1,&quot;text&quot;:&quot;test 1&quot;}]')
+    client.get { search! :q=&gt;'test' }
+    assert_equal(:get,client.transport.method, &quot;Get block should override method even if post bang is used&quot;)
+    client.delete { search? :q=&gt;'test', :__method=&gt;:post }
+    assert_equal(:post,client.transport.method, &quot;:__method=&gt;:post should override block setting and method suffix&quot;)
+  end
   
   private
     def with_http_responder(responder)</diff>
      <filename>test/test_client.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>8cd15c339b8ed13d9e0464557b0c5e9f4384e3a8</id>
    </parent>
  </parents>
  <author>
    <name>Hayes Davis</name>
    <email>hayes@appozite.com</email>
  </author>
  <url>http://github.com/hayesdavis/grackle/commit/7041b6408e387eca9ba89d3e5ef33ef766cbc1f7</url>
  <id>7041b6408e387eca9ba89d3e5ef33ef766cbc1f7</id>
  <committed-date>2009-10-29T19:45:57-07:00</committed-date>
  <authored-date>2009-10-29T19:45:57-07:00</authored-date>
  <message>Added new block syntax for HTTP methods that aren't GET and POST. Also added support for building a request path that has a part that is not a valid Ruby method. These two changes give Grackle better support for the upcoming Twitter Lists API and its more RESTful approach. This is version 0.1.6.</message>
  <tree>d633f2e7561d320d6973046e4670716e7f2a45b1</tree>
  <committer>
    <name>Hayes Davis</name>
    <email>hayes@appozite.com</email>
  </committer>
</commit>
