citygrid_api 0.0.7 → 0.0.9
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/VERSION +1 -1
- data/citygrid_api.gemspec +3 -2
- data/lib/citygrid/api/advertising/image.rb +5 -5
- data/lib/citygrid/api.rb +119 -99
- data/lib/citygrid/citygrid_exceptions.rb +199 -0
- data/test/helper.rb +6 -6
- metadata +21 -20
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0. | 
| 1 | 
            +
            0.0.9
         | 
    
        data/citygrid_api.gemspec
    CHANGED
    
    | @@ -5,11 +5,11 @@ | |
| 5 5 |  | 
| 6 6 | 
             
            Gem::Specification.new do |s|
         | 
| 7 7 | 
             
              s.name = "citygrid_api"
         | 
| 8 | 
            -
              s.version = "0.0. | 
| 8 | 
            +
              s.version = "0.0.9"
         | 
| 9 9 |  | 
| 10 10 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 11 | 
             
              s.authors = ["Elpizo Choi", "Joseph Chen"]
         | 
| 12 | 
            -
              s.date = "2012- | 
| 12 | 
            +
              s.date = "2012-03-01"
         | 
| 13 13 | 
             
              s.description = "Ruby wrapper for CityGrid APIs"
         | 
| 14 14 | 
             
              s.email = "Joseph.Chen@citygridmedia.com"
         | 
| 15 15 | 
             
              s.extra_rdoc_files = [
         | 
| @@ -105,6 +105,7 @@ Gem::Specification.new do |s| | |
| 105 105 | 
             
                "lib/citygrid/api/mutable.rb",
         | 
| 106 106 | 
             
                "lib/citygrid/api/response.rb",
         | 
| 107 107 | 
             
                "lib/citygrid/api/searchable.rb",
         | 
| 108 | 
            +
                "lib/citygrid/citygrid_exceptions.rb",
         | 
| 108 109 | 
             
                "lib/citygrid/details.rb",
         | 
| 109 110 | 
             
                "lib/citygrid/listing.rb",
         | 
| 110 111 | 
             
                "lib/citygrid/offers.rb",
         | 
| @@ -13,11 +13,11 @@ class CityGrid | |
| 13 13 | 
             
                        :body => {"mutateOperationListResource" => [
         | 
| 14 14 | 
             
                          {
         | 
| 15 15 | 
             
                            "operand" => {
         | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 16 | 
            +
                              "imageType" => type,
         | 
| 17 | 
            +
                              "imageName" => name,
         | 
| 18 | 
            +
                              "imageFormat" => format,
         | 
| 19 | 
            +
                              "image" => image_data
         | 
| 20 | 
            +
                            },
         | 
| 21 21 | 
             
                            "operator" => "ADD",
         | 
| 22 22 | 
             
                            "userId" => user_id
         | 
| 23 23 | 
             
                          }
         | 
    
        data/lib/citygrid/api.rb
    CHANGED
    
    | @@ -1,9 +1,11 @@ | |
| 1 1 | 
             
            require "httparty"
         | 
| 2 2 | 
             
            require "json"
         | 
| 3 | 
            +
            require "citygrid/citygrid_exceptions"
         | 
| 3 4 |  | 
| 4 5 | 
             
            class CityGrid
         | 
| 5 6 | 
             
              class API 
         | 
| 6 7 | 
             
                include HTTParty
         | 
| 8 | 
            +
                include CityGridExceptions
         | 
| 7 9 | 
             
                #debug_output $stderr
         | 
| 8 10 |  | 
| 9 11 | 
             
                DEFAULT_HEADERS = {
         | 
| @@ -83,128 +85,146 @@ class CityGrid | |
| 83 85 | 
             
                      "options" => Net::HTTP::Options
         | 
| 84 86 | 
             
                    }
         | 
| 85 87 |  | 
| 86 | 
            -
             | 
| 87 | 
            -
                     | 
| 88 | 
            -
                     | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
                    
         | 
| 94 | 
            -
                       | 
| 95 | 
            -
                       | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                       | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
                         | 
| 109 | 
            -
                          Rails.logger.info req.to_curl
         | 
| 110 | 
            -
                        else
         | 
| 111 | 
            -
                          puts req.to_curl
         | 
| 112 | 
            -
                        end
         | 
| 113 | 
            -
                      end
         | 
| 114 | 
            -
                      
         | 
| 115 | 
            -
                      if !response.parsed_response.is_a?(Hash)
         | 
| 116 | 
            -
                        raise ResponseParseError.new req, response
         | 
| 117 | 
            -
                      elsif response["errors"]
         | 
| 118 | 
            -
                        raise ResponseError.new req, response["errors"], response
         | 
| 119 | 
            -
                      elsif response["message"] && response["message"] == "Invalid Token or Expired"
         | 
| 120 | 
            -
                        raise InvalidAuthToken.new
         | 
| 88 | 
            +
                  def strip_unsafe_params options
         | 
| 89 | 
            +
                    puts "OPTIONS: #{options}"
         | 
| 90 | 
            +
                    unsafe_params = { 
         | 
| 91 | 
            +
                                      :password => "[FILTERED]", :securityCode => "[FILTERED]",
         | 
| 92 | 
            +
                                      :cardNumber => "[FILTERED]", :expirationMonth => "[FILTERED]",
         | 
| 93 | 
            +
                                      :expirationYear => "[FILTERED]"
         | 
| 94 | 
            +
                                    }
         | 
| 95 | 
            +
                    if !options[:query].nil?
         | 
| 96 | 
            +
                      to_merge[:query] = options[:query].merge(unsafe_params.select { |k| options.keys.include? k })
         | 
| 97 | 
            +
                      return options.merge(to_merge)
         | 
| 98 | 
            +
                    end
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  # 
         | 
| 102 | 
            +
                  def parse_multiple_responses response
         | 
| 103 | 
            +
                    parsing = response.values.select{ |x| x.is_a? Array }.first
         | 
| 104 | 
            +
                    if parsing.nil? || parsing == []
         | 
| 105 | 
            +
                      ap "Response was too hard to parse... letting it through..."
         | 
| 106 | 
            +
                      return parsing
         | 
| 107 | 
            +
                    elsif parsing != nil && parsing != []
         | 
| 108 | 
            +
                      if parsing[0]["response"]
         | 
| 109 | 
            +
                        parsing = [parsing[0]["response"]["code"], parsing[0]["response"]["message"]]
         | 
| 110 | 
            +
                        return parsing
         | 
| 121 111 | 
             
                      else
         | 
| 122 | 
            -
                         | 
| 112 | 
            +
                        # this accomodates geocode response which does not contain a response node
         | 
| 113 | 
            +
                        ap "Response was too hard to parse... letting it through..."
         | 
| 114 | 
            +
                        return nil
         | 
| 123 115 | 
             
                      end
         | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
                      raise  | 
| 116 | 
            +
                    else
         | 
| 117 | 
            +
                      # We should figure out a better way to do this
         | 
| 118 | 
            +
                      raise CityGridExceptions::APIError.new "Received a JSON error code but it could not be parsed: #{response}"
         | 
| 127 119 | 
             
                    end
         | 
| 128 120 | 
             
                  end
         | 
| 129 121 |  | 
| 130 | 
            -
                  #  | 
| 131 | 
            -
                   | 
| 132 | 
            -
             | 
| 133 | 
            -
                    
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                       | 
| 122 | 
            +
                  # Transform response into API::Response object
         | 
| 123 | 
            +
                  # or throw exception if an error exists
         | 
| 124 | 
            +
                  def request_and_handle http_method, path, options
         | 
| 125 | 
            +
                    if http_method.is_a?(String) || http_method.is_a?(Symbol)
         | 
| 126 | 
            +
                      http_method = HTTP_METHODS[http_method.to_s]
         | 
| 127 | 
            +
                      raise "Unknown http method: #{http_method}" unless http_method
         | 
| 136 128 | 
             
                    end
         | 
| 137 | 
            -
                  end
         | 
| 138 129 |  | 
| 139 | 
            -
             | 
| 140 | 
            -
                     | 
| 130 | 
            +
                    req_options = default_options.dup
         | 
| 131 | 
            +
                    req_options = req_options.merge(options)
         | 
| 141 132 |  | 
| 142 | 
            -
                     | 
| 143 | 
            -
             | 
| 144 | 
            -
                      self.response = response
         | 
| 145 | 
            -
                      
         | 
| 146 | 
            -
                      super "API returned error message", request
         | 
| 147 | 
            -
                    end
         | 
| 148 | 
            -
                  end
         | 
| 149 | 
            -
                  
         | 
| 150 | 
            -
                  class RequestError < APIError
         | 
| 151 | 
            -
                    attr_accessor :inner_exception
         | 
| 133 | 
            +
                    raise ConfigurationError.new "No endpoint defined" if !path || path.empty?
         | 
| 134 | 
            +
                    raise ConfigurationError.new "No hostname defined" if !req_options[:base_uri] || req_options[:base_uri].empty?
         | 
| 152 135 |  | 
| 153 | 
            -
                     | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 136 | 
            +
                    # prepare request and sanitized request for logs
         | 
| 137 | 
            +
                    #puts "Options after strip unsafe: #{strip_unsafe_params(req_options)}"
         | 
| 138 | 
            +
                    #puts "options before that: #{req_options}"
         | 
| 139 | 
            +
                    #safe_req_options = strip_unsafe_params(req_options)
         | 
| 140 | 
            +
                    req = HTTParty::Request.new http_method, path, req_options
         | 
| 141 | 
            +
                    #req_to_output = HTTParty::Request.new http_method, path, safe_req_options
         | 
| 142 | 
            +
                    # ap "HERE ARE THE INGREDIENTS OF THE REQUEST:"
         | 
| 143 | 
            +
                    # ap "http_method is: #{http_method}"
         | 
| 144 | 
            +
                    # ap "path is: #{path}"
         | 
| 145 | 
            +
                    # ap "req_options is: #{req_options}"
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                    begin
         | 
| 148 | 
            +
                      response = req.perform
         | 
| 149 | 
            +
                    rescue => ex
         | 
| 150 | 
            +
                      raise CityGridExceptions::RequestError.new req, ex
         | 
| 151 | 
            +
                    ensure
         | 
| 152 | 
            +
                      if defined?(Rails.logger)
         | 
| 153 | 
            +
                        Rails.logger.info req.to_curl
         | 
| 154 | 
            +
                      else
         | 
| 155 | 
            +
                        puts req.to_curl
         | 
| 156 | 
            +
                        ap response
         | 
| 157 | 
            +
                      end
         | 
| 157 158 | 
             
                    end
         | 
| 158 | 
            -
                  end
         | 
| 159 | 
            -
                  
         | 
| 160 | 
            -
                  class ResponseParseError < APIError
         | 
| 161 | 
            -
                    attr_accessor :server_msg, :description, :raw_response
         | 
| 162 | 
            -
                    def initialize request, response
         | 
| 163 | 
            -
                      self.raw_response = response
         | 
| 164 | 
            -
                      # parse Tomcat error report
         | 
| 165 | 
            -
                      if response.match /<title>Apache Tomcat.* - Error report<\/title>/
         | 
| 166 | 
            -
                        response.scan(/<p><b>(message|description)<\/b> *<u>(.*?)<\/u><\/p>/).each do |match|
         | 
| 167 | 
            -
                          case match[0]
         | 
| 168 | 
            -
                          when "message"
         | 
| 169 | 
            -
                            self.server_msg = match[1]
         | 
| 170 | 
            -
                          when "description"
         | 
| 171 | 
            -
                            self.description = match[1]       
         | 
| 172 | 
            -
                          end
         | 
| 173 | 
            -
                        end
         | 
| 174 | 
            -
             | 
| 175 | 
            -
                        error_body = response.match(/<body>(.*?)<\/body>/m)[1]
         | 
| 176 | 
            -
             | 
| 177 | 
            -
                        msg = <<-EOS
         | 
| 178 | 
            -
                        Unexpected response format. Expected response to be a hash, but was instead:\n#{error_body}\n
         | 
| 179 | 
            -
                        EOS
         | 
| 180 159 |  | 
| 181 | 
            -
             | 
| 160 | 
            +
                    begin 
         | 
| 161 | 
            +
                      # catch unparsable responses (html etc)
         | 
| 162 | 
            +
                      if !response.parsed_response.is_a?(Hash)
         | 
| 163 | 
            +
                        ap "[gem] the response was unparsable (response was not a hash)"
         | 
| 164 | 
            +
                        raise CityGridExceptions::ResponseParseError.new req, response
         | 
| 165 | 
            +
                      # catch responses not in new response format
         | 
| 166 | 
            +
                      elsif response["errors"]
         | 
| 167 | 
            +
                        ap "[gem] An error in the old response format was caught.  Raising a general response error..."
         | 
| 168 | 
            +
                        raise CityGridExceptions::ResponseError.new req, response["errors"], response
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                      # Parse and handle new response codes 
         | 
| 171 | 
            +
                      elsif (response["response"] && response["response"]["code"] != "SUCCESS") && 
         | 
| 172 | 
            +
                            (response["response"] && response["response"]["code"] != 200) && 
         | 
| 173 | 
            +
                            (response["response"] && response["response"]["code"] != 400) 
         | 
| 174 | 
            +
                        error_code = response["response"]["code"]
         | 
| 175 | 
            +
                        ap "[gem] The response was contained in the first level of the response hash.  Below:"
         | 
| 176 | 
            +
                        ap response
         | 
| 177 | 
            +
                        ap "found error code: #{error_code}"
         | 
| 178 | 
            +
                        ap "****************************************************************************"
         | 
| 179 | 
            +
                        raise CityGridExceptions.appropriate_error(error_code).new req, response, response["response"]["message"].to_s #+ " " + CityGridExceptions.print_superclasses(error_code)
         | 
| 180 | 
            +
                      # if the response is a nested hash/nested hash containing arrays
         | 
| 181 | 
            +
                      elsif response["totalNumEntries"] && response["response"].nil?
         | 
| 182 | 
            +
                        ap "[gem] now parsing a response with multiple entries: #{response}"
         | 
| 183 | 
            +
                        error_code = parse_multiple_responses(response)
         | 
| 184 | 
            +
                        ap "the error code that came back is #{error_code}"
         | 
| 185 | 
            +
                        if error_code.nil? || error_code == []
         | 
| 186 | 
            +
                          ap "[gem] passing over this for now"
         | 
| 187 | 
            +
                          return CityGrid::API::Response.new response # pass over for now
         | 
| 188 | 
            +
                        elsif error_code[0] == "SUCCESS" || error_code[0] == 200 || error_code[0] == 400
         | 
| 189 | 
            +
                          return CityGrid::API::Response.new response
         | 
| 190 | 
            +
                        else 
         | 
| 191 | 
            +
                          ap "[gem] we found an error and it was #{error_code[1]}"
         | 
| 192 | 
            +
                            raise CityGridExceptions.appropriate_error(error_code[0]).new req, response, error_code[1].to_s  + " "# + CityGridExceptions.print_superclasses(error_code[0])
         | 
| 193 | 
            +
                        end
         | 
| 182 194 | 
             
                      else
         | 
| 183 | 
            -
                         | 
| 184 | 
            -
                        Unexpected response format. Expected response to be a hash, but was instead:\n#{response.parsed_response}\n
         | 
| 185 | 
            -
                        EOS
         | 
| 186 | 
            -
             | 
| 187 | 
            -
                        super msg, request
         | 
| 195 | 
            +
                        return CityGrid::API::Response.new response
         | 
| 188 196 | 
             
                      end
         | 
| 197 | 
            +
                    rescue => ex
         | 
| 198 | 
            +
                      ap "The gem threw an error: #{ex}"
         | 
| 199 | 
            +
                      raise ex if CityGrid.raise_errors?
         | 
| 189 200 | 
             
                    end
         | 
| 190 201 | 
             
                  end
         | 
| 191 202 |  | 
| 192 | 
            -
             | 
| 193 | 
            -
                    def initialize message = "Invalid Token or Expired"
         | 
| 194 | 
            -
                      super message
         | 
| 195 | 
            -
                    end
         | 
| 196 | 
            -
                  end
         | 
| 203 | 
            +
               # Errors
         | 
| 197 204 |  | 
| 198 | 
            -
                  class  | 
| 199 | 
            -
                    def initialize
         | 
| 200 | 
            -
                      super  | 
| 205 | 
            +
                  class MUSHPendingChanges <StandardError
         | 
| 206 | 
            +
                    def initialize message = "The are currently pending changes in the mush.  Cannot update."
         | 
| 207 | 
            +
                      super message
         | 
| 201 208 | 
             
                    end
         | 
| 202 209 | 
             
                  end
         | 
| 203 210 |  | 
| 211 | 
            +
                  # class InvalidAuthToken < StandardError
         | 
| 212 | 
            +
                  #   def initialize message = "Invalid Token or Expired"
         | 
| 213 | 
            +
                  #     super message
         | 
| 214 | 
            +
                  #   end
         | 
| 215 | 
            +
                  # end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                  # class MissingAuthToken < StandardError
         | 
| 218 | 
            +
                  #   def initialize
         | 
| 219 | 
            +
                  #     super "Missing authToken - token is required"
         | 
| 220 | 
            +
                  #   end
         | 
| 221 | 
            +
                  # end
         | 
| 222 | 
            +
                  
         | 
| 204 223 | 
             
                  class ConfigurationError < StandardError
         | 
| 205 224 | 
             
                    def initialize message = "Invalid Configuration"
         | 
| 206 225 | 
             
                      super message
         | 
| 207 226 | 
             
                    end
         | 
| 208 227 | 
             
                  end
         | 
| 209 228 | 
             
                end
         | 
| 210 | 
            -
              end
         | 
| 229 | 
            +
              end
         | 
| 230 | 
            +
            end
         | 
| @@ -0,0 +1,199 @@ | |
| 1 | 
            +
            module CityGridExceptions
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              # Define parent error classes
         | 
| 4 | 
            +
              # All errors thrown in the API should extend APIError - Level 1
         | 
| 5 | 
            +
              class APIError < StandardError
         | 
| 6 | 
            +
                attr_accessor :request
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                def initialize request, response, msg = "An API error occurred"
         | 
| 9 | 
            +
                  super msg
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              # Level 2 - These represent three different error scenarios:
         | 
| 14 | 
            +
              # 1.  Response is totally not parsable to JSON
         | 
| 15 | 
            +
              # 2.  The API call/parameters were malformed
         | 
| 16 | 
            +
              # 3.  The request was fine but their was an error API side
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              class ResponseParseError < APIError
         | 
| 19 | 
            +
                attr_accessor :server_msg, :description, :raw_response
         | 
| 20 | 
            +
                def initialize request, response, msg = nil
         | 
| 21 | 
            +
                  self.raw_response = response
         | 
| 22 | 
            +
                  # parse Tomcat error report
         | 
| 23 | 
            +
                  if response.match /<title>Apache Tomcat.* - Error report<\/title>/
         | 
| 24 | 
            +
                    response.scan(/<p><b>(message|description)<\/b> *<u>(.*?)<\/u><\/p>/).each do |match|
         | 
| 25 | 
            +
                      case match[0]
         | 
| 26 | 
            +
                      when "message"
         | 
| 27 | 
            +
                        self.server_msg = match[1]
         | 
| 28 | 
            +
                      when "description"
         | 
| 29 | 
            +
                        self.description = match[1]       
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    error_body = response.match(/<body>(.*?)<\/body>/m)[1]
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    msg = <<-EOS
         | 
| 36 | 
            +
                    Unexpected response format. Expected response to be a hash, but was instead:\n#{error_body}\n
         | 
| 37 | 
            +
                    EOS
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    super msg, request
         | 
| 40 | 
            +
                  else
         | 
| 41 | 
            +
                    msg = <<-EOS
         | 
| 42 | 
            +
                    Unexpected response format. Expected response to be a hash, but was instead:\n#{response.parsed_response}\n
         | 
| 43 | 
            +
                    EOS
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    super msg, request
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              class RequestError < APIError
         | 
| 51 | 
            +
                attr_accessor :inner_exception
         | 
| 52 | 
            +
                
         | 
| 53 | 
            +
                def initialize request, response, msg = nil
         | 
| 54 | 
            +
                  self.inner_exception = inner_exception
         | 
| 55 | 
            +
                  self.request = request
         | 
| 56 | 
            +
                  super msg, request
         | 
| 57 | 
            +
                  #super msg || "Error while performing request: #{inner_exception.message}", request
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              class ResponseError < APIError
         | 
| 62 | 
            +
                attr_accessor :errors, :response
         | 
| 63 | 
            +
                
         | 
| 64 | 
            +
                def initialize request, errors, response
         | 
| 65 | 
            +
                  self.errors = errors
         | 
| 66 | 
            +
                  self.response = response
         | 
| 67 | 
            +
                  
         | 
| 68 | 
            +
                  super "API returned error message", request
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              # Level 3
         | 
| 73 | 
            +
              class GeneralError < APIError; end
         | 
| 74 | 
            +
              class HeaderError < APIError; end
         | 
| 75 | 
            +
              class AuthenticationError < APIError; end
         | 
| 76 | 
            +
              class AuthorizationError < APIError; end
         | 
| 77 | 
            +
              class OperatorError < RequestError; end
         | 
| 78 | 
            +
              class GeneralDataError < APIError; end
         | 
| 79 | 
            +
              class SpecificDataError < APIError; end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              # Level 4
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              # General Errors
         | 
| 84 | 
            +
              class SystemErrorTryAgainError < GeneralError; end
         | 
| 85 | 
            +
              class SystemErrorUnknownError < GeneralError; end
         | 
| 86 | 
            +
              class BadRequestTypeError < GeneralError; end 
         | 
| 87 | 
            +
             | 
| 88 | 
            +
             | 
| 89 | 
            +
             | 
| 90 | 
            +
              # HeaderErrors < RequestError
         | 
| 91 | 
            +
              class ContentTypeRequiredError < HeaderError; end
         | 
| 92 | 
            +
              class ContentTypeInvalidError < HeaderError; end
         | 
| 93 | 
            +
              class AcceptRequiredError < HeaderError; end 
         | 
| 94 | 
            +
              class AcceptInvalidError < HeaderError; end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              # Authentication Error
         | 
| 97 | 
            +
              class AuthTokenInvalidError < AuthenticationError; end
         | 
| 98 | 
            +
              class AuthTokenExpiredError < AuthenticationError; end
         | 
| 99 | 
            +
              class AuthTokenNoneError    < AuthenticationError; end
         | 
| 100 | 
            +
              class UsernameRequiredError < AuthenticationError; end
         | 
| 101 | 
            +
              class PasswordRequiredError < AuthenticationError; end
         | 
| 102 | 
            +
              class AccountNotFoundError  < AuthenticationError; end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
             #Authorization Error
         | 
| 105 | 
            +
             class PermissionDeniedError < AuthorizationError; end
         | 
| 106 | 
            +
             class NoPermissionsError < AuthorizationError; end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
             # Request Error
         | 
| 109 | 
            +
             class ParameterRequiredError            < RequestError; end
         | 
| 110 | 
            +
             class ParameterRequiredConditionalError < RequestError; end
         | 
| 111 | 
            +
             class ParameterInvalidError             < RequestError; end
         | 
| 112 | 
            +
             class ParameterFormatError              < RequestError; end
         | 
| 113 | 
            +
             class ParameterNotSupportedError        < RequestError; end
         | 
| 114 | 
            +
             class ParameterRangeTooLowError         < RequestError; end
         | 
| 115 | 
            +
             class ParameterRangeTooHighError        < RequestError; end
         | 
| 116 | 
            +
             class ParameterSizeLimitExceededError   < RequestError; end
         | 
| 117 | 
            +
             class ParameterCannotBeZeroError        < RequestError; end
         | 
| 118 | 
            +
             class ParameterOnlyOne                  < RequestError; end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
             # Operator Error
         | 
| 121 | 
            +
             class OperatorInvalidError < OperatorError; end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
             # General Data Errors
         | 
| 124 | 
            +
             class EntityNotFoundError      < GeneralDataError; end
         | 
| 125 | 
            +
             class EntityExistsError        < GeneralDataError; end
         | 
| 126 | 
            +
             class EntityLimitError         < GeneralDataError; end
         | 
| 127 | 
            +
             class EntityAlreadyInUseError  < GeneralDataError; end
         | 
| 128 | 
            +
             class EntityExpiredError       < GeneralDataError; end
         | 
| 129 | 
            +
             class EntityInactiveError      < GeneralDataError; end
         | 
| 130 | 
            +
             class EntityNotEligibleError   < GeneralDataError; end
         | 
| 131 | 
            +
             class EntityNotModifiedError   < GeneralDataError; end
         | 
| 132 | 
            +
             class EntityStateInvalidError  < GeneralDataError; end
         | 
| 133 | 
            +
             class EntityMissingDataError   < GeneralDataError; end
         | 
| 134 | 
            +
             class DataNotFoundError        < GeneralDataError; end
         | 
| 135 | 
            +
             class AssociationExistsError   < GeneralDataError; end
         | 
| 136 | 
            +
             class NoAssociationExistsError < GeneralDataError; end
         | 
| 137 | 
            +
             class DuplicateError           < GeneralDataError; end
         | 
| 138 | 
            +
             class DateBeforeDateError      < GeneralDataError; end
         | 
| 139 | 
            +
             class RemoveNotAllowedError    < GeneralDataError; end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
            #data errors - specific
         | 
| 142 | 
            +
             class MopExpiredError           < SpecificDataError; end
         | 
| 143 | 
            +
             class AccountInactiveError      < SpecificDataError; end
         | 
| 144 | 
            +
             class AccountDelinquentError    < SpecificDataError; end
         | 
| 145 | 
            +
             class MonthlyBudgetReachedError < SpecificDataError; end
         | 
| 146 | 
            +
             class QuotaExceededError        < SpecificDataError; end
         | 
| 147 | 
            +
             class RateExceededError         < SpecificDataError; end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
            # unused errors
         | 
| 150 | 
            +
            #400 => RequestError,
         | 
| 151 | 
            +
            @possible_errors =
         | 
| 152 | 
            +
             { 
         | 
| 153 | 
            +
              0 => ResponseError, nil => ResponseParseError, "" => ResponseParseError, 
         | 
| 154 | 
            +
              401 => AuthenticationError, 403 => RequestError, 405 => RequestError, 406 => HeaderError, 
         | 
| 155 | 
            +
              500 => ResponseError, "SYSTEM_ERROR_TRY_AGAIN" => SystemErrorTryAgainError,
         | 
| 156 | 
            +
              "SYSTEM_ERROR_UNKNOWN" => SystemErrorUnknownError, "BAD_REQUEST_TYPE" => BadRequestTypeError,
         | 
| 157 | 
            +
              "HEADER_CONTENT_TYPE_IS_REQUIRED" => ContentTypeRequiredError, "HEADER_CONTENT_TYPE_INVALID" => ContentTypeInvalidError,
         | 
| 158 | 
            +
              "HEADER_ACCEPT_IS_REQUIRED" => AcceptRequiredError, "HEADER_ACCEPT_INVALID" => AcceptInvalidError,
         | 
| 159 | 
            +
              "AUTH_TOKEN_INVALID" => AuthTokenInvalidError, "AUTH_TOKEN_EXPIRED" => AuthTokenExpiredError,
         | 
| 160 | 
            +
              "AUTH_TOKEN_NONE" => AuthTokenNoneError,
         | 
| 161 | 
            +
              "USERNAME_IS_REQUIRED" => UsernameRequiredError, "PASSWORD_IS_REQUIRED" => PasswordRequiredError,
         | 
| 162 | 
            +
              "ACCOUNT_NOT_FOUND" => AccountNotFoundError, "PERMISSION_DENIED" => PermissionDeniedError,
         | 
| 163 | 
            +
              "NO_PERMISSIONS" => NoPermissionsError, "PARAMETER_REQUIRED" => ParameterRequiredError,
         | 
| 164 | 
            +
              "PARAMETER_REQUIRED_CONDITIONAL" => ParameterRequiredConditionalError, "PARAMETER_INVALID" => ParameterInvalidError,
         | 
| 165 | 
            +
              "PARAMETER_FORMAT" => ParameterFormatError, "PARAMETER_NOT_SUPPORTED" => ParameterNotSupportedError,
         | 
| 166 | 
            +
              "PARAMETER_RANGE_TOO_LOW" => ParameterRangeTooLowError, "PARAMETER_RANGE_TOO_HIGH" => ParameterRangeTooHighError,
         | 
| 167 | 
            +
              "PARAMETER_SIZE_LIMIT_EXCEEDED" => ParameterSizeLimitExceededError, "PARAMETER_CANNOT_BE_ZERO" => ParameterCannotBeZeroError,
         | 
| 168 | 
            +
              "PARAMETER_ONLY_ONE" => ParameterOnlyOne, "OPERATOR_INVALID" => OperatorInvalidError,
         | 
| 169 | 
            +
              "ENTITY_NOT_FOUND" => EntityNotFoundError, "ENTITY_EXISTS" => EntityExistsError,
         | 
| 170 | 
            +
              "ENTITY_LIMIT" => EntityLimitError, "ENTITY_ALREADY_IN_USE" => EntityAlreadyInUseError,
         | 
| 171 | 
            +
              "ENTITY_EXPIRED" => EntityExpiredError, "ENTITY_INACTIVE" => EntityInactiveError,
         | 
| 172 | 
            +
              "ENTITY_NOT_ELIGIBLE" => EntityNotEligibleError, "ENTITY_NOT_MODIFIED" => EntityNotModifiedError,
         | 
| 173 | 
            +
              "ENTITY_STATE_INVALID" => EntityStateInvalidError, "ENTITY_MISSING_DATA" => EntityMissingDataError,
         | 
| 174 | 
            +
              "DATA_NOT_FOUND" => DataNotFoundError, "ASSOCIATION_EXISTS" => AssociationExistsError,
         | 
| 175 | 
            +
              "NO_ASSOCIATION_EXISTS" =>  NoAssociationExistsError, "DUPLICATE" =>  DuplicateError,
         | 
| 176 | 
            +
              "DATE_BEFORE_DATE" => DateBeforeDateError, "REMOVE_NOT_ALLOWED" => RemoveNotAllowedError,
         | 
| 177 | 
            +
              "MOP_EXPIRED" => MopExpiredError, "ACCOUNT_INACTIVE" => AccountInactiveError,
         | 
| 178 | 
            +
              "ACCOUNT_DELINQUENT" => AccountDelinquentError, "MONTHLY_BUDGET_REACHED" => MonthlyBudgetReachedError,
         | 
| 179 | 
            +
              "QUOTA_EXCEEDED" => QuotaExceededError,"RATE_EXCEEDED" =>  RateExceededError
         | 
| 180 | 
            +
              }
         | 
| 181 | 
            +
             | 
| 182 | 
            +
              def CityGridExceptions.appropriate_error error_code
         | 
| 183 | 
            +
                if @possible_errors.include?(error_code)
         | 
| 184 | 
            +
                  return @possible_errors[error_code]
         | 
| 185 | 
            +
                else
         | 
| 186 | 
            +
                  return APIError
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
              end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
              def CityGridExceptions.print_superclasses error_code
         | 
| 191 | 
            +
                begin
         | 
| 192 | 
            +
                  raise appropriate_error[error_code]
         | 
| 193 | 
            +
                rescue => ex
         | 
| 194 | 
            +
                  class_hierarchy = ex.class.ancestors
         | 
| 195 | 
            +
                  class_hierarchy.slice!(class_hierarchy.index(StandardError)..-1)
         | 
| 196 | 
            +
                  return class_hierarchy.reverse.join("::")
         | 
| 197 | 
            +
                end
         | 
| 198 | 
            +
              end
         | 
| 199 | 
            +
            end
         | 
    
        data/test/helper.rb
    CHANGED
    
    | @@ -22,9 +22,9 @@ unless defined? IN_DASHBOARD | |
| 22 22 |  | 
| 23 23 | 
             
              # load default config
         | 
| 24 24 | 
             
              CityGrid.load_config File.expand_path(File.join(File.dirname(__FILE__), '..', 'citygrid_api.yml.sample'))
         | 
| 25 | 
            -
             | 
| 25 | 
            +
             | 
| 26 26 | 
             
              # CityGrid.load_config File.expand_path(File.join(File.dirname(__FILE__), '..', 'citygrid_api.yml.sandbox'))
         | 
| 27 | 
            -
             | 
| 27 | 
            +
             | 
| 28 28 | 
             
              # Run code with rescue so that exceptions
         | 
| 29 29 | 
             
              # will be printed, but won't stop test suite
         | 
| 30 30 | 
             
              def run_with_rescue
         | 
| @@ -45,10 +45,10 @@ unless defined? IN_DASHBOARD | |
| 45 45 | 
             
                  false # return false
         | 
| 46 46 | 
             
                end
         | 
| 47 47 | 
             
              end
         | 
| 48 | 
            -
             | 
| 48 | 
            +
             | 
| 49 49 | 
             
              # patch in VCR
         | 
| 50 50 | 
             
              require 'vcr'
         | 
| 51 | 
            -
             | 
| 51 | 
            +
             | 
| 52 52 | 
             
              VCR.config do |c|
         | 
| 53 53 | 
             
                c.cassette_library_dir = 'fixtures/vcr_cassettes'
         | 
| 54 54 | 
             
                c.stub_with :webmock
         | 
| @@ -69,8 +69,8 @@ unless defined? IN_DASHBOARD | |
| 69 69 | 
             
                    #  end
         | 
| 70 70 | 
             
                    # end
         | 
| 71 71 | 
             
                  end
         | 
| 72 | 
            -
             | 
| 72 | 
            +
             | 
| 73 73 | 
             
                end
         | 
| 74 74 | 
             
              end
         | 
| 75 | 
            -
             | 
| 75 | 
            +
             | 
| 76 76 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: citygrid_api
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.9
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -10,11 +10,11 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2012- | 
| 13 | 
            +
            date: 2012-03-01 00:00:00.000000000Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: httparty
         | 
| 17 | 
            -
              requirement: & | 
| 17 | 
            +
              requirement: &70321245070140 !ruby/object:Gem::Requirement
         | 
| 18 18 | 
             
                none: false
         | 
| 19 19 | 
             
                requirements:
         | 
| 20 20 | 
             
                - - ~>
         | 
| @@ -22,10 +22,10 @@ dependencies: | |
| 22 22 | 
             
                    version: 0.8.1
         | 
| 23 23 | 
             
              type: :runtime
         | 
| 24 24 | 
             
              prerelease: false
         | 
| 25 | 
            -
              version_requirements: * | 
| 25 | 
            +
              version_requirements: *70321245070140
         | 
| 26 26 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 27 27 | 
             
              name: json
         | 
| 28 | 
            -
              requirement: & | 
| 28 | 
            +
              requirement: &70321245069540 !ruby/object:Gem::Requirement
         | 
| 29 29 | 
             
                none: false
         | 
| 30 30 | 
             
                requirements:
         | 
| 31 31 | 
             
                - - =
         | 
| @@ -33,10 +33,10 @@ dependencies: | |
| 33 33 | 
             
                    version: 1.5.3
         | 
| 34 34 | 
             
              type: :runtime
         | 
| 35 35 | 
             
              prerelease: false
         | 
| 36 | 
            -
              version_requirements: * | 
| 36 | 
            +
              version_requirements: *70321245069540
         | 
| 37 37 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 38 38 | 
             
              name: riot
         | 
| 39 | 
            -
              requirement: & | 
| 39 | 
            +
              requirement: &70321245068820 !ruby/object:Gem::Requirement
         | 
| 40 40 | 
             
                none: false
         | 
| 41 41 | 
             
                requirements:
         | 
| 42 42 | 
             
                - - ~>
         | 
| @@ -44,10 +44,10 @@ dependencies: | |
| 44 44 | 
             
                    version: 0.12.4
         | 
| 45 45 | 
             
              type: :runtime
         | 
| 46 46 | 
             
              prerelease: false
         | 
| 47 | 
            -
              version_requirements: * | 
| 47 | 
            +
              version_requirements: *70321245068820
         | 
| 48 48 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 49 49 | 
             
              name: awesome_print
         | 
| 50 | 
            -
              requirement: & | 
| 50 | 
            +
              requirement: &70321245068080 !ruby/object:Gem::Requirement
         | 
| 51 51 | 
             
                none: false
         | 
| 52 52 | 
             
                requirements:
         | 
| 53 53 | 
             
                - - ~>
         | 
| @@ -55,10 +55,10 @@ dependencies: | |
| 55 55 | 
             
                    version: 0.4.0
         | 
| 56 56 | 
             
              type: :runtime
         | 
| 57 57 | 
             
              prerelease: false
         | 
| 58 | 
            -
              version_requirements: * | 
| 58 | 
            +
              version_requirements: *70321245068080
         | 
| 59 59 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 60 60 | 
             
              name: bundler
         | 
| 61 | 
            -
              requirement: & | 
| 61 | 
            +
              requirement: &70321245067160 !ruby/object:Gem::Requirement
         | 
| 62 62 | 
             
                none: false
         | 
| 63 63 | 
             
                requirements:
         | 
| 64 64 | 
             
                - - ~>
         | 
| @@ -66,10 +66,10 @@ dependencies: | |
| 66 66 | 
             
                    version: 1.0.0
         | 
| 67 67 | 
             
              type: :development
         | 
| 68 68 | 
             
              prerelease: false
         | 
| 69 | 
            -
              version_requirements: * | 
| 69 | 
            +
              version_requirements: *70321245067160
         | 
| 70 70 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 71 71 | 
             
              name: jeweler
         | 
| 72 | 
            -
              requirement: & | 
| 72 | 
            +
              requirement: &70321245063220 !ruby/object:Gem::Requirement
         | 
| 73 73 | 
             
                none: false
         | 
| 74 74 | 
             
                requirements:
         | 
| 75 75 | 
             
                - - ~>
         | 
| @@ -77,10 +77,10 @@ dependencies: | |
| 77 77 | 
             
                    version: 1.6.2
         | 
| 78 78 | 
             
              type: :development
         | 
| 79 79 | 
             
              prerelease: false
         | 
| 80 | 
            -
              version_requirements: * | 
| 80 | 
            +
              version_requirements: *70321245063220
         | 
| 81 81 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 82 82 | 
             
              name: rcov
         | 
| 83 | 
            -
              requirement: & | 
| 83 | 
            +
              requirement: &70321245062700 !ruby/object:Gem::Requirement
         | 
| 84 84 | 
             
                none: false
         | 
| 85 85 | 
             
                requirements:
         | 
| 86 86 | 
             
                - - ! '>='
         | 
| @@ -88,10 +88,10 @@ dependencies: | |
| 88 88 | 
             
                    version: '0'
         | 
| 89 89 | 
             
              type: :development
         | 
| 90 90 | 
             
              prerelease: false
         | 
| 91 | 
            -
              version_requirements: * | 
| 91 | 
            +
              version_requirements: *70321245062700
         | 
| 92 92 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 93 93 | 
             
              name: vcr
         | 
| 94 | 
            -
              requirement: & | 
| 94 | 
            +
              requirement: &70321245061660 !ruby/object:Gem::Requirement
         | 
| 95 95 | 
             
                none: false
         | 
| 96 96 | 
             
                requirements:
         | 
| 97 97 | 
             
                - - ! '>='
         | 
| @@ -99,10 +99,10 @@ dependencies: | |
| 99 99 | 
             
                    version: '0'
         | 
| 100 100 | 
             
              type: :development
         | 
| 101 101 | 
             
              prerelease: false
         | 
| 102 | 
            -
              version_requirements: * | 
| 102 | 
            +
              version_requirements: *70321245061660
         | 
| 103 103 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 104 104 | 
             
              name: webmock
         | 
| 105 | 
            -
              requirement: & | 
| 105 | 
            +
              requirement: &70321245059820 !ruby/object:Gem::Requirement
         | 
| 106 106 | 
             
                none: false
         | 
| 107 107 | 
             
                requirements:
         | 
| 108 108 | 
             
                - - ! '>='
         | 
| @@ -110,7 +110,7 @@ dependencies: | |
| 110 110 | 
             
                    version: '0'
         | 
| 111 111 | 
             
              type: :development
         | 
| 112 112 | 
             
              prerelease: false
         | 
| 113 | 
            -
              version_requirements: * | 
| 113 | 
            +
              version_requirements: *70321245059820
         | 
| 114 114 | 
             
            description: Ruby wrapper for CityGrid APIs
         | 
| 115 115 | 
             
            email: Joseph.Chen@citygridmedia.com
         | 
| 116 116 | 
             
            executables: []
         | 
| @@ -207,6 +207,7 @@ files: | |
| 207 207 | 
             
            - lib/citygrid/api/mutable.rb
         | 
| 208 208 | 
             
            - lib/citygrid/api/response.rb
         | 
| 209 209 | 
             
            - lib/citygrid/api/searchable.rb
         | 
| 210 | 
            +
            - lib/citygrid/citygrid_exceptions.rb
         | 
| 210 211 | 
             
            - lib/citygrid/details.rb
         | 
| 211 212 | 
             
            - lib/citygrid/listing.rb
         | 
| 212 213 | 
             
            - lib/citygrid/offers.rb
         |