google-spreadsheet-ruby 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/google_spreadsheet.rb +128 -94
- metadata +40 -15
    
        data/lib/google_spreadsheet.rb
    CHANGED
    
    | @@ -8,7 +8,8 @@ require "open-uri" | |
| 8 8 | 
             
            require "cgi"
         | 
| 9 9 | 
             
            require "uri"
         | 
| 10 10 | 
             
            require "rubygems"
         | 
| 11 | 
            -
            require  | 
| 11 | 
            +
            require 'nokogiri'
         | 
| 12 | 
            +
             | 
| 12 13 | 
             
            require "oauth"
         | 
| 13 14 | 
             
            Net::HTTP.version_1_2
         | 
| 14 15 |  | 
| @@ -98,14 +99,6 @@ module GoogleSpreadsheet | |
| 98 99 | 
             
                      return CGI.escapeHTML(str.to_s())
         | 
| 99 100 | 
             
                    end
         | 
| 100 101 |  | 
| 101 | 
            -
                    def as_utf8(str)
         | 
| 102 | 
            -
                      if str.respond_to?(:force_encoding)
         | 
| 103 | 
            -
                        str.force_encoding("UTF-8")
         | 
| 104 | 
            -
                      else
         | 
| 105 | 
            -
                        str
         | 
| 106 | 
            -
                      end
         | 
| 107 | 
            -
                    end
         | 
| 108 | 
            -
                    
         | 
| 109 102 | 
             
                end
         | 
| 110 103 |  | 
| 111 104 |  | 
| @@ -142,11 +135,8 @@ module GoogleSpreadsheet | |
| 142 135 |  | 
| 143 136 | 
             
                    # Restores session using return value of auth_tokens method of previous session.
         | 
| 144 137 | 
             
                    def initialize(auth_tokens = nil, oauth_token = nil)
         | 
| 145 | 
            -
                       | 
| 146 | 
            -
             | 
| 147 | 
            -
                      else
         | 
| 148 | 
            -
                        @auth_tokens = auth_tokens
         | 
| 149 | 
            -
                      end
         | 
| 138 | 
            +
                      @oauth_token = oauth_token
         | 
| 139 | 
            +
                      @auth_tokens = auth_tokens || {}
         | 
| 150 140 | 
             
                    end
         | 
| 151 141 |  | 
| 152 142 | 
             
                    # Authenticates with given +mail+ and +password+, and updates current session object
         | 
| @@ -176,10 +166,11 @@ module GoogleSpreadsheet | |
| 176 166 | 
             
                    attr_accessor :on_auth_fail
         | 
| 177 167 |  | 
| 178 168 | 
             
                    def auth_header(auth) #:nodoc:
         | 
| 179 | 
            -
                       | 
| 180 | 
            -
             | 
| 169 | 
            +
                      token = auth == :none ? nil : @auth_tokens[auth]
         | 
| 170 | 
            +
                      if token
         | 
| 171 | 
            +
                        return {"Authorization" => "GoogleLogin auth=#{token}"}
         | 
| 181 172 | 
             
                      else
         | 
| 182 | 
            -
                        return { | 
| 173 | 
            +
                        return {}
         | 
| 183 174 | 
             
                      end
         | 
| 184 175 | 
             
                    end
         | 
| 185 176 |  | 
| @@ -194,10 +185,10 @@ module GoogleSpreadsheet | |
| 194 185 | 
             
                      query = encode_query(params)
         | 
| 195 186 | 
             
                      doc = request(:get, "https://spreadsheets.google.com/feeds/spreadsheets/private/full?#{query}")
         | 
| 196 187 | 
             
                      result = []
         | 
| 197 | 
            -
                       | 
| 198 | 
            -
                        title =  | 
| 199 | 
            -
                        url =  | 
| 200 | 
            -
                          "link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[0]["href"] | 
| 188 | 
            +
                      doc.css("feed > entry").each() do |entry|
         | 
| 189 | 
            +
                        title = entry.css("title").text
         | 
| 190 | 
            +
                        url = entry.css(
         | 
| 191 | 
            +
                          "link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[0]["href"]
         | 
| 201 192 | 
             
                        result.push(Spreadsheet.new(self, url, title))
         | 
| 202 193 | 
             
                      end
         | 
| 203 194 | 
             
                      return result
         | 
| @@ -260,68 +251,70 @@ module GoogleSpreadsheet | |
| 260 251 | 
             
                      EOS
         | 
| 261 252 |  | 
| 262 253 | 
             
                      doc = request(:post, feed_url, :data => xml, :auth => :writely)
         | 
| 263 | 
            -
                      ss_url =  | 
| 264 | 
            -
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[ | 
| 254 | 
            +
                      ss_url = doc.css(
         | 
| 255 | 
            +
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']").first['href']
         | 
| 265 256 | 
             
                      return Spreadsheet.new(self, ss_url, title)
         | 
| 266 257 | 
             
                    end
         | 
| 267 258 |  | 
| 268 259 | 
             
                    def request(method, url, params = {}) #:nodoc:
         | 
| 269 260 | 
             
                      # Always uses HTTPS.
         | 
| 270 | 
            -
                       | 
| 261 | 
            +
                      url = url.gsub(%r{^http://}, "https://")
         | 
| 271 262 | 
             
                      data = params[:data]
         | 
| 272 263 | 
             
                      auth = params[:auth] || :wise
         | 
| 273 264 | 
             
                      if params[:header]
         | 
| 274 | 
            -
                         | 
| 265 | 
            +
                        extra_header = params[:header]
         | 
| 266 | 
            +
                      elsif data
         | 
| 267 | 
            +
                        extra_header = {"Content-Type" => "application/atom+xml"}
         | 
| 275 268 | 
             
                      else
         | 
| 276 | 
            -
                         | 
| 269 | 
            +
                        extra_header = {}
         | 
| 277 270 | 
             
                      end
         | 
| 278 271 | 
             
                      response_type = params[:response_type] || :xml
         | 
| 279 272 |  | 
| 273 | 
            +
                      while true
         | 
| 274 | 
            +
                        response = request_raw(method, url, data, extra_header, auth)
         | 
| 275 | 
            +
                        if response.code == "401" && @on_auth_fail && @on_auth_fail.call()
         | 
| 276 | 
            +
                          next
         | 
| 277 | 
            +
                        end
         | 
| 278 | 
            +
                        if !(response.code =~ /^2/)
         | 
| 279 | 
            +
                          raise(
         | 
| 280 | 
            +
                            response.code == "401" ? AuthenticationError : GoogleSpreadsheet::Error,
         | 
| 281 | 
            +
                            "Response code #{response.code} for #{method} #{url}: " +
         | 
| 282 | 
            +
                            CGI.unescapeHTML(response.body))
         | 
| 283 | 
            +
                        end
         | 
| 284 | 
            +
                        return convert_response(response, response_type)
         | 
| 285 | 
            +
                      end
         | 
| 286 | 
            +
                    end
         | 
| 287 | 
            +
                    
         | 
| 288 | 
            +
                  private
         | 
| 289 | 
            +
                    
         | 
| 290 | 
            +
                    def request_raw(method, url, data, extra_header, auth)
         | 
| 280 291 | 
             
                      if @oauth_token
         | 
| 281 | 
            -
                        
         | 
| 282 292 | 
             
                        if method == :delete || method == :get
         | 
| 283 | 
            -
                           | 
| 293 | 
            +
                          return @oauth_token.__send__(method, url, extra_header)
         | 
| 284 294 | 
             
                        else
         | 
| 285 | 
            -
                           | 
| 295 | 
            +
                          return @oauth_token.__send__(method, url, data, extra_header)
         | 
| 286 296 | 
             
                        end
         | 
| 287 | 
            -
                        return convert_response(response, response_type)
         | 
| 288 | 
            -
                        
         | 
| 289 297 | 
             
                      else
         | 
| 290 | 
            -
                        
         | 
| 298 | 
            +
                        uri = URI.parse(url)
         | 
| 291 299 | 
             
                        http = Net::HTTP.new(uri.host, uri.port)
         | 
| 292 300 | 
             
                        http.use_ssl = true
         | 
| 293 301 | 
             
                        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         | 
| 294 302 | 
             
                        http.start() do
         | 
| 295 | 
            -
                           | 
| 296 | 
            -
             | 
| 297 | 
            -
             | 
| 298 | 
            -
                             | 
| 299 | 
            -
             | 
| 300 | 
            -
                             | 
| 301 | 
            -
                              response = http.__send__(method, path, data, header)
         | 
| 302 | 
            -
                            end
         | 
| 303 | 
            -
                            if response.code == "401" && @on_auth_fail && @on_auth_fail.call()
         | 
| 304 | 
            -
                              next
         | 
| 305 | 
            -
                            end
         | 
| 306 | 
            -
                            if !(response.code =~ /^2/)
         | 
| 307 | 
            -
                              raise(
         | 
| 308 | 
            -
                                response.code == "401" ? AuthenticationError : GoogleSpreadsheet::Error,
         | 
| 309 | 
            -
                                "Response code #{response.code} for #{method} #{url}: " +
         | 
| 310 | 
            -
                                CGI.unescapeHTML(response.body))
         | 
| 311 | 
            -
                            end
         | 
| 312 | 
            -
                            return convert_response(response, response_type)
         | 
| 303 | 
            +
                          path = uri.path + (uri.query ? "?#{uri.query}" : "")
         | 
| 304 | 
            +
                          header = auth_header(auth).merge(extra_header)
         | 
| 305 | 
            +
                          if method == :delete || method == :get
         | 
| 306 | 
            +
                            return http.__send__(method, path, header)
         | 
| 307 | 
            +
                          else
         | 
| 308 | 
            +
                            return http.__send__(method, path, data, header)
         | 
| 313 309 | 
             
                          end
         | 
| 314 310 | 
             
                        end
         | 
| 315 | 
            -
                        
         | 
| 316 311 | 
             
                      end
         | 
| 317 312 | 
             
                    end
         | 
| 318 313 |  | 
| 319 | 
            -
                  private
         | 
| 320 | 
            -
                    
         | 
| 321 314 | 
             
                    def convert_response(response, response_type)
         | 
| 322 315 | 
             
                      case response_type
         | 
| 323 316 | 
             
                        when :xml
         | 
| 324 | 
            -
                          return  | 
| 317 | 
            +
                          return Nokogiri.XML(response.body)
         | 
| 325 318 | 
             
                        when :raw
         | 
| 326 319 | 
             
                          return response.body
         | 
| 327 320 | 
             
                        else
         | 
| @@ -337,9 +330,10 @@ module GoogleSpreadsheet | |
| 337 330 | 
             
                        "service" => auth.to_s(),
         | 
| 338 331 | 
             
                        "source" => "Gimite-RubyGoogleSpreadsheet-1.00",
         | 
| 339 332 | 
             
                      }
         | 
| 333 | 
            +
                      header = {"Content-Type" => "application/x-www-form-urlencoded"}
         | 
| 340 334 | 
             
                      response = request(:post,
         | 
| 341 335 | 
             
                        "https://www.google.com/accounts/ClientLogin",
         | 
| 342 | 
            -
                        :data => encode_query(params), :auth => :none, :header =>  | 
| 336 | 
            +
                        :data => encode_query(params), :auth => :none, :header => header, :response_type => :raw)
         | 
| 343 337 | 
             
                      @auth_tokens[auth] = response.slice(/^Auth=(.*)$/, 1)
         | 
| 344 338 | 
             
                    end
         | 
| 345 339 |  | 
| @@ -378,12 +372,12 @@ module GoogleSpreadsheet | |
| 378 372 | 
             
                    def tables_feed_url
         | 
| 379 373 | 
             
                      return "https://spreadsheets.google.com/feeds/#{self.key}/tables"
         | 
| 380 374 | 
             
                    end
         | 
| 381 | 
            -
             | 
| 375 | 
            +
             | 
| 382 376 | 
             
                    # URL of feed used in document list feed API.
         | 
| 383 377 | 
             
                    def document_feed_url
         | 
| 384 378 | 
             
                      return "https://docs.google.com/feeds/documents/private/full/spreadsheet%3A#{self.key}"
         | 
| 385 379 | 
             
                    end
         | 
| 386 | 
            -
             | 
| 380 | 
            +
             | 
| 387 381 | 
             
                    # Creates copy of this spreadsheet with the given name.
         | 
| 388 382 | 
             
                    def duplicate(new_name = nil)
         | 
| 389 383 | 
             
                      new_name ||= (@title ? "Copy of " + @title : "Untitled")
         | 
| @@ -396,8 +390,8 @@ module GoogleSpreadsheet | |
| 396 390 | 
             
                        "Slug" => URI.encode(new_name),
         | 
| 397 391 | 
             
                      }
         | 
| 398 392 | 
             
                      doc = @session.request(:post, url, :data => ods, :auth => :writely, :header => header)
         | 
| 399 | 
            -
                      ss_url =  | 
| 400 | 
            -
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']")[ | 
| 393 | 
            +
                      ss_url = doc.css(
         | 
| 394 | 
            +
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#worksheetsfeed']").first['href']
         | 
| 401 395 | 
             
                      return Spreadsheet.new(@session, ss_url, title)
         | 
| 402 396 | 
             
                    end
         | 
| 403 397 |  | 
| @@ -409,14 +403,32 @@ module GoogleSpreadsheet | |
| 409 403 | 
             
                        :auth => :writely, :header => {"If-Match" => "*"})
         | 
| 410 404 | 
             
                    end
         | 
| 411 405 |  | 
| 406 | 
            +
                    # Renames title of the spreadsheet.
         | 
| 407 | 
            +
                    def rename(title)
         | 
| 408 | 
            +
                      doc = @session.request(:get, self.document_feed_url)
         | 
| 409 | 
            +
                      edit_url = doc.css("link[@rel='edit']").first['href']
         | 
| 410 | 
            +
                      xml = <<-"EOS"
         | 
| 411 | 
            +
                        <atom:entry
         | 
| 412 | 
            +
                            xmlns:atom="http://www.w3.org/2005/Atom"
         | 
| 413 | 
            +
                            xmlns:docs="http://schemas.google.com/docs/2007">
         | 
| 414 | 
            +
                          <atom:category
         | 
| 415 | 
            +
                            scheme="http://schemas.google.com/g/2005#kind"
         | 
| 416 | 
            +
                            term="http://schemas.google.com/docs/2007#spreadsheet" label="spreadsheet"/>
         | 
| 417 | 
            +
                          <atom:title>#{h(title)}</atom:title>
         | 
| 418 | 
            +
                        </atom:entry>
         | 
| 419 | 
            +
                      EOS
         | 
| 420 | 
            +
             | 
| 421 | 
            +
                      @session.request(:put, edit_url, :data => xml)
         | 
| 422 | 
            +
                    end
         | 
| 423 | 
            +
                    
         | 
| 412 424 | 
             
                    # Returns worksheets of the spreadsheet as array of GoogleSpreadsheet::Worksheet.
         | 
| 413 425 | 
             
                    def worksheets
         | 
| 414 426 | 
             
                      doc = @session.request(:get, @worksheets_feed_url)
         | 
| 415 427 | 
             
                      result = []
         | 
| 416 | 
            -
                       | 
| 417 | 
            -
                        title =  | 
| 418 | 
            -
                        url =  | 
| 419 | 
            -
                          "link[@rel='http://schemas.google.com/spreadsheets/2006#cellsfeed']")[ | 
| 428 | 
            +
                      doc.css('entry').each() do |entry|
         | 
| 429 | 
            +
                        title = entry.css('title').text
         | 
| 430 | 
            +
                        url = entry.css(
         | 
| 431 | 
            +
                          "link[@rel='http://schemas.google.com/spreadsheets/2006#cellsfeed']").first['href']
         | 
| 420 432 | 
             
                        result.push(Worksheet.new(@session, self, url, title))
         | 
| 421 433 | 
             
                      end
         | 
| 422 434 | 
             
                      return result.freeze()
         | 
| @@ -433,15 +445,15 @@ module GoogleSpreadsheet | |
| 433 445 | 
             
                        </entry>
         | 
| 434 446 | 
             
                      EOS
         | 
| 435 447 | 
             
                      doc = @session.request(:post, @worksheets_feed_url, :data => xml)
         | 
| 436 | 
            -
                      url =  | 
| 437 | 
            -
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#cellsfeed']")[ | 
| 448 | 
            +
                      url = doc.css(
         | 
| 449 | 
            +
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#cellsfeed']").first['href']
         | 
| 438 450 | 
             
                      return Worksheet.new(@session, self, url, title)
         | 
| 439 451 | 
             
                    end
         | 
| 440 452 |  | 
| 441 453 | 
             
                    # Returns list of tables in the spreadsheet.
         | 
| 442 454 | 
             
                    def tables
         | 
| 443 455 | 
             
                      doc = @session.request(:get, self.tables_feed_url)
         | 
| 444 | 
            -
                      return doc. | 
| 456 | 
            +
                      return doc.css('entry').map(){ |e| Table.new(@session, e) }.freeze()
         | 
| 445 457 | 
             
                    end
         | 
| 446 458 |  | 
| 447 459 | 
             
                end
         | 
| @@ -454,8 +466,9 @@ module GoogleSpreadsheet | |
| 454 466 |  | 
| 455 467 | 
             
                    def initialize(session, entry) #:nodoc:
         | 
| 456 468 | 
             
                      @columns = {}
         | 
| 457 | 
            -
                      @worksheet_title =  | 
| 458 | 
            -
                      @records_url =  | 
| 469 | 
            +
                      @worksheet_title = entry.css('gs|worksheet').first['name']
         | 
| 470 | 
            +
                      @records_url = entry.css("content")[0]["src"]
         | 
| 471 | 
            +
                      @edit_url = entry.css("link[@rel='edit']")[0]['href']
         | 
| 459 472 | 
             
                      @session = session
         | 
| 460 473 | 
             
                    end
         | 
| 461 474 |  | 
| @@ -465,7 +478,7 @@ module GoogleSpreadsheet | |
| 465 478 | 
             
                    # Adds a record.
         | 
| 466 479 | 
             
                    def add_record(values)
         | 
| 467 480 | 
             
                      fields = ""
         | 
| 468 | 
            -
                      values.each do |name, value|
         | 
| 481 | 
            +
                      values.each() do |name, value|
         | 
| 469 482 | 
             
                        fields += "<gs:field name='#{h(name)}'>#{h(value)}</gs:field>"
         | 
| 470 483 | 
             
                      end
         | 
| 471 484 | 
             
                      xml =<<-EOS
         | 
| @@ -481,18 +494,24 @@ module GoogleSpreadsheet | |
| 481 494 | 
             
                    # Returns records in the table.
         | 
| 482 495 | 
             
                    def records
         | 
| 483 496 | 
             
                      doc = @session.request(:get, @records_url)
         | 
| 484 | 
            -
                      return doc. | 
| 497 | 
            +
                      return doc.css('entry').map(){ |e| Record.new(@session, e) }
         | 
| 498 | 
            +
                    end
         | 
| 499 | 
            +
                    
         | 
| 500 | 
            +
                    # Deletes this table. Deletion takes effect right away without calling save().
         | 
| 501 | 
            +
                    def delete
         | 
| 502 | 
            +
                      @session.request(:delete, @edit_url, :header => {"If-Match" => "*"})
         | 
| 485 503 | 
             
                    end
         | 
| 486 504 |  | 
| 487 505 | 
             
                end
         | 
| 488 506 |  | 
| 489 507 | 
             
                # Use GoogleSpreadsheet::Table#records to get GoogleSpreadsheet::Record objects.
         | 
| 490 508 | 
             
                class Record < Hash
         | 
| 509 | 
            +
                    include(Util)
         | 
| 491 510 |  | 
| 492 511 | 
             
                    def initialize(session, entry) #:nodoc:
         | 
| 493 512 | 
             
                      @session = session
         | 
| 494 | 
            -
                       | 
| 495 | 
            -
                        self[ | 
| 513 | 
            +
                      entry.css('gs|field').each() do |field|
         | 
| 514 | 
            +
                        self[field["name"]] = field.inner_text
         | 
| 496 515 | 
             
                      end
         | 
| 497 516 | 
             
                    end
         | 
| 498 517 |  | 
| @@ -652,18 +671,19 @@ module GoogleSpreadsheet | |
| 652 671 | 
             
                    # Note that changes you made by []= is discarded if you haven't called save().
         | 
| 653 672 | 
             
                    def reload()
         | 
| 654 673 | 
             
                      doc = @session.request(:get, @cells_feed_url)
         | 
| 655 | 
            -
                      @max_rows = doc. | 
| 656 | 
            -
                      @max_cols = doc. | 
| 657 | 
            -
                      @title =  | 
| 674 | 
            +
                      @max_rows = doc.css('gs|rowCount').text.to_i
         | 
| 675 | 
            +
                      @max_cols = doc.css('gs|colCount').text.to_i
         | 
| 676 | 
            +
                      @title = doc.css('feed > title')[0].text
         | 
| 658 677 |  | 
| 659 678 | 
             
                      @cells = {}
         | 
| 660 679 | 
             
                      @input_values = {}
         | 
| 661 | 
            -
                       | 
| 662 | 
            -
                        cell = entry. | 
| 680 | 
            +
                      doc.css('feed > entry').each() do |entry|
         | 
| 681 | 
            +
                        cell = entry.css('gs|cell').first
         | 
| 663 682 | 
             
                        row = cell["row"].to_i()
         | 
| 664 683 | 
             
                        col = cell["col"].to_i()
         | 
| 665 | 
            -
                        @cells[[row, col]] =  | 
| 666 | 
            -
                        @input_values[[row, col]] =  | 
| 684 | 
            +
                        @cells[[row, col]] = cell.inner_text
         | 
| 685 | 
            +
                        @input_values[[row, col]] = cell["inputValue"]
         | 
| 686 | 
            +
                        
         | 
| 667 687 | 
             
                      end
         | 
| 668 688 | 
             
                      @modified.clear()
         | 
| 669 689 | 
             
                      @meta_modified = false
         | 
| @@ -677,7 +697,7 @@ module GoogleSpreadsheet | |
| 677 697 | 
             
                      if @meta_modified
         | 
| 678 698 |  | 
| 679 699 | 
             
                        ws_doc = @session.request(:get, self.worksheet_feed_url)
         | 
| 680 | 
            -
                        edit_url = ws_doc. | 
| 700 | 
            +
                        edit_url = ws_doc.css("link[@rel='edit']").first['href']
         | 
| 681 701 | 
             
                        xml = <<-"EOS"
         | 
| 682 702 | 
             
                          <entry xmlns='http://www.w3.org/2005/Atom'
         | 
| 683 703 | 
             
                                 xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
         | 
| @@ -704,9 +724,10 @@ module GoogleSpreadsheet | |
| 704 724 | 
             
                        url = "#{@cells_feed_url}?return-empty=true&min-row=#{rows.min}&max-row=#{rows.max}" +
         | 
| 705 725 | 
             
                          "&min-col=#{cols.min}&max-col=#{cols.max}"
         | 
| 706 726 | 
             
                        doc = @session.request(:get, url)
         | 
| 707 | 
            -
             | 
| 708 | 
            -
             | 
| 709 | 
            -
                           | 
| 727 | 
            +
             | 
| 728 | 
            +
                        doc.css('entry').each() do |entry|
         | 
| 729 | 
            +
                          row = entry.css('gs|cell').first['row'].to_i
         | 
| 730 | 
            +
                          col = entry.css('gs|cell').first['col'].to_i
         | 
| 710 731 | 
             
                          cell_entries[[row, col]] = entry
         | 
| 711 732 | 
             
                        end
         | 
| 712 733 |  | 
| @@ -723,8 +744,8 @@ module GoogleSpreadsheet | |
| 723 744 | 
             
                          for row, col in chunk
         | 
| 724 745 | 
             
                            value = @cells[[row, col]]
         | 
| 725 746 | 
             
                            entry = cell_entries[[row, col]]
         | 
| 726 | 
            -
                            id = entry. | 
| 727 | 
            -
                            edit_url = entry. | 
| 747 | 
            +
                            id = entry.css('id').text
         | 
| 748 | 
            +
                            edit_url = entry.css("link[@rel='edit']").first['href']
         | 
| 728 749 | 
             
                            xml << <<-EOS
         | 
| 729 750 | 
             
                              <entry>
         | 
| 730 751 | 
             
                                <batch:id>#{h(row)},#{h(col)}</batch:id>
         | 
| @@ -741,15 +762,15 @@ module GoogleSpreadsheet | |
| 741 762 | 
             
                          EOS
         | 
| 742 763 |  | 
| 743 764 | 
             
                          result = @session.request(:post, "#{@cells_feed_url}/batch", :data => xml)
         | 
| 744 | 
            -
                           | 
| 745 | 
            -
                            interrupted = entry. | 
| 765 | 
            +
                          result.css('atom|entry').each() do |entry|
         | 
| 766 | 
            +
                            interrupted = entry.css('batch|interrupted').first
         | 
| 746 767 | 
             
                            if interrupted
         | 
| 747 768 | 
             
                              raise(GoogleSpreadsheet::Error, "Update has failed: %s" %
         | 
| 748 769 | 
             
                                interrupted["reason"])
         | 
| 749 770 | 
             
                            end
         | 
| 750 | 
            -
                            if !(entry. | 
| 771 | 
            +
                            if !(entry.css('batch|status').first['code'] =~ /^2/)
         | 
| 751 772 | 
             
                              raise(GoogleSpreadsheet::Error, "Updating cell %s has failed: %s" %
         | 
| 752 | 
            -
                                [entry. | 
| 773 | 
            +
                                [entry.css('atom|id').text, entry.css('batch|status').first['reason']])
         | 
| 753 774 | 
             
                            end
         | 
| 754 775 | 
             
                          end
         | 
| 755 776 |  | 
| @@ -771,7 +792,7 @@ module GoogleSpreadsheet | |
| 771 792 | 
             
                    # Deletes this worksheet. Deletion takes effect right away without calling save().
         | 
| 772 793 | 
             
                    def delete()
         | 
| 773 794 | 
             
                      ws_doc = @session.request(:get, self.worksheet_feed_url)
         | 
| 774 | 
            -
                      edit_url = ws_doc. | 
| 795 | 
            +
                      edit_url = ws_doc.css("link[@rel='edit']").first['href']
         | 
| 775 796 | 
             
                      @session.request(:delete, edit_url)
         | 
| 776 797 | 
             
                    end
         | 
| 777 798 |  | 
| @@ -783,9 +804,12 @@ module GoogleSpreadsheet | |
| 783 804 | 
             
                    # Creates table for the worksheet and returns GoogleSpreadsheet::Table.
         | 
| 784 805 | 
             
                    # See this document for details:
         | 
| 785 806 | 
             
                    # http://code.google.com/intl/en/apis/spreadsheets/docs/3.0/developers_guide_protocol.html#TableFeeds
         | 
| 786 | 
            -
                    def add_table(table_title, summary, columns)
         | 
| 807 | 
            +
                    def add_table(table_title, summary, columns, options)
         | 
| 808 | 
            +
                      default_options = { :header_row => 1, :num_rows => 0, :start_row => 2}
         | 
| 809 | 
            +
                      options = default_options.merge(options)
         | 
| 810 | 
            +
                      
         | 
| 787 811 | 
             
                      column_xml = ""
         | 
| 788 | 
            -
                      columns.each do |index, name|
         | 
| 812 | 
            +
                      columns.each() do |index, name|
         | 
| 789 813 | 
             
                        column_xml += "<gs:column index='#{h(index)}' name='#{h(name)}'/>\n"
         | 
| 790 814 | 
             
                      end
         | 
| 791 815 |  | 
| @@ -795,8 +819,8 @@ module GoogleSpreadsheet | |
| 795 819 | 
             
                          <title type='text'>#{h(table_title)}</title>
         | 
| 796 820 | 
             
                          <summary type='text'>#{h(summary)}</summary>
         | 
| 797 821 | 
             
                          <gs:worksheet name='#{h(self.title)}' />
         | 
| 798 | 
            -
                          <gs:header row=' | 
| 799 | 
            -
                          <gs:data numRows=' | 
| 822 | 
            +
                          <gs:header row='#{options[:header_row]}' />
         | 
| 823 | 
            +
                          <gs:data numRows='#{options[:num_rows]}' startRow='#{options[:start_row]}'>
         | 
| 800 824 | 
             
                            #{column_xml}
         | 
| 801 825 | 
             
                          </gs:data>
         | 
| 802 826 | 
             
                        </entry>
         | 
| @@ -811,6 +835,16 @@ module GoogleSpreadsheet | |
| 811 835 | 
             
                      return self.spreadsheet.tables.select(){ |t| t.worksheet_title == self.title }
         | 
| 812 836 | 
             
                    end
         | 
| 813 837 |  | 
| 838 | 
            +
                    # List feed URL of the worksheet.
         | 
| 839 | 
            +
                    def list_feed_url
         | 
| 840 | 
            +
                      # Gets the worksheets metafeed.
         | 
| 841 | 
            +
                      entry = @session.request(:get, self.worksheet_feed_url)
         | 
| 842 | 
            +
             | 
| 843 | 
            +
                      # Gets the URL of list-based feed for the given spreadsheet.
         | 
| 844 | 
            +
                      return entry.css(
         | 
| 845 | 
            +
                        "link[@rel='http://schemas.google.com/spreadsheets/2006#listfeed']").first['href']
         | 
| 846 | 
            +
                    end
         | 
| 847 | 
            +
             | 
| 814 848 | 
             
                end
         | 
| 815 849 |  | 
| 816 850 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: google-spreadsheet-ruby
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
               | 
| 4 | 
            +
              hash: 31
         | 
| 5 | 
            +
              prerelease: false
         | 
| 6 | 
            +
              segments: 
         | 
| 7 | 
            +
              - 0
         | 
| 8 | 
            +
              - 1
         | 
| 9 | 
            +
              - 2
         | 
| 10 | 
            +
              version: 0.1.2
         | 
| 5 11 | 
             
            platform: ruby
         | 
| 6 12 | 
             
            authors: 
         | 
| 7 13 | 
             
            - Hiroshi Ichikawa
         | 
| @@ -9,29 +15,42 @@ autorequire: | |
| 9 15 | 
             
            bindir: bin
         | 
| 10 16 | 
             
            cert_chain: []
         | 
| 11 17 |  | 
| 12 | 
            -
            date: 2010- | 
| 18 | 
            +
            date: 2010-09-24 00:00:00 +09:00
         | 
| 13 19 | 
             
            default_executable: 
         | 
| 14 20 | 
             
            dependencies: 
         | 
| 15 21 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 16 | 
            -
              name:  | 
| 17 | 
            -
               | 
| 18 | 
            -
               | 
| 19 | 
            -
             | 
| 22 | 
            +
              name: nokogiri
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         | 
| 25 | 
            +
                none: false
         | 
| 20 26 | 
             
                requirements: 
         | 
| 21 27 | 
             
                - - ">="
         | 
| 22 28 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 23 | 
            -
                     | 
| 24 | 
            -
             | 
| 29 | 
            +
                    hash: 113
         | 
| 30 | 
            +
                    segments: 
         | 
| 31 | 
            +
                    - 1
         | 
| 32 | 
            +
                    - 4
         | 
| 33 | 
            +
                    - 3
         | 
| 34 | 
            +
                    - 1
         | 
| 35 | 
            +
                    version: 1.4.3.1
         | 
| 36 | 
            +
              type: :runtime
         | 
| 37 | 
            +
              version_requirements: *id001
         | 
| 25 38 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 26 39 | 
             
              name: oauth
         | 
| 27 | 
            -
               | 
| 28 | 
            -
               | 
| 29 | 
            -
             | 
| 40 | 
            +
              prerelease: false
         | 
| 41 | 
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 42 | 
            +
                none: false
         | 
| 30 43 | 
             
                requirements: 
         | 
| 31 44 | 
             
                - - ">="
         | 
| 32 45 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 46 | 
            +
                    hash: 31
         | 
| 47 | 
            +
                    segments: 
         | 
| 48 | 
            +
                    - 0
         | 
| 49 | 
            +
                    - 3
         | 
| 50 | 
            +
                    - 6
         | 
| 33 51 | 
             
                    version: 0.3.6
         | 
| 34 | 
            -
             | 
| 52 | 
            +
              type: :runtime
         | 
| 53 | 
            +
              version_requirements: *id002
         | 
| 35 54 | 
             
            description: This is a library to read/write Google Spreadsheet.
         | 
| 36 55 | 
             
            email: 
         | 
| 37 56 | 
             
            - gimite+github@gmail.com
         | 
| @@ -55,21 +74,27 @@ rdoc_options: | |
| 55 74 | 
             
            require_paths: 
         | 
| 56 75 | 
             
            - lib
         | 
| 57 76 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 77 | 
            +
              none: false
         | 
| 58 78 | 
             
              requirements: 
         | 
| 59 79 | 
             
              - - ">="
         | 
| 60 80 | 
             
                - !ruby/object:Gem::Version 
         | 
| 81 | 
            +
                  hash: 3
         | 
| 82 | 
            +
                  segments: 
         | 
| 83 | 
            +
                  - 0
         | 
| 61 84 | 
             
                  version: "0"
         | 
| 62 | 
            -
              version: 
         | 
| 63 85 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 86 | 
            +
              none: false
         | 
| 64 87 | 
             
              requirements: 
         | 
| 65 88 | 
             
              - - ">="
         | 
| 66 89 | 
             
                - !ruby/object:Gem::Version 
         | 
| 90 | 
            +
                  hash: 3
         | 
| 91 | 
            +
                  segments: 
         | 
| 92 | 
            +
                  - 0
         | 
| 67 93 | 
             
                  version: "0"
         | 
| 68 | 
            -
              version: 
         | 
| 69 94 | 
             
            requirements: []
         | 
| 70 95 |  | 
| 71 96 | 
             
            rubyforge_project: 
         | 
| 72 | 
            -
            rubygems_version: 1.3. | 
| 97 | 
            +
            rubygems_version: 1.3.7
         | 
| 73 98 | 
             
            signing_key: 
         | 
| 74 99 | 
             
            specification_version: 2
         | 
| 75 100 | 
             
            summary: This is a library to read/write Google Spreadsheet.
         |