├── .travis.yml ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── examples └── NaturalLanguageClassifier │ ├── README.md │ ├── classify.rb │ ├── delete.rb │ ├── file2csv.rb │ └── train.rb ├── lib └── watson-api-client.rb └── watson-api-client.gemspec /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.2.0 4 | - 2.1 5 | - 2.0 6 | script: "ruby lib/watson-api-client.rb" 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rest-client' 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Takashi SUGA . 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | watson-api-client - An IBM Watson™ API client 2 | ================================================================ 3 | 4 | [![Gem Version](https://badge.fury.io/rb/watson-api-client.svg)](http://badge.fury.io/rb/watson-api-client) 5 | 6 | The [watson-api-client](http://rubygems.org/gems/watson-api-client) is a gem to use REST API on the IBM Watson™ Developer Cloud. 7 | 8 | It wraps the [rest-client](https://rubygems.org/gems/rest-client) REST API using [Swagger](http://swagger.io/) documents retrievable from the [Watson API Reference](https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/). 9 | 10 | 11 | Installation 12 | ------------ 13 | 14 | The watson-api-client gem can be installed by running: 15 | 16 | gem install watson-api-client 17 | 18 | Since watson-api-client is dependent on the rest-client, when the rest-client is not installed, the rest-client is also installed automatically. 19 | 20 | 21 | Documentation 22 | ------------- 23 | 24 | The simple API documentation for the watson-api-client is available on [RubyDoc.info](http://rubydoc.info/gems/watson-api-client). 25 | 26 | However, most of the classes and methods of this gem are not described in the above document because they are dynamically defined. 27 | Instead, you can output to the standard output the actual those list of classes and methods when you run the lib/watson-api-client.rb directly, or 28 | you can also use the following method to view a list of known APIs: 29 | 30 | ``` 31 | require 'watson-api-client' 32 | 33 | puts WatsonAPIClient::AvailableAPIs 34 | ``` 35 | 36 | Source Code 37 | ----------- 38 | 39 | The source code for the watson-api-client is available on [GitHub](https://github.com/suchowan/watson-api-client). 40 | 41 | 42 | Example Usage 43 | ------------- 44 | 45 | ###Preparation 46 | 47 | The watson-api-client is a gem to use REST API on the IBM Watson™ Developer Cloud. 48 | To enable these API, you have to do the user registration to the IBM Bluemix™ beforehand, make the services effective, and be relating them to your application. 49 | For more information, refer to 'Getting Started' in '[Table of Contents for Services Documentation](http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/)'. 50 | 51 | ###VisualRecognition example 52 | 53 | Let's use 'Visual Recognition' service. 54 | 55 | service = WatsonAPIClient::VisualRecognition.new(:version=>'2018-03-19', :user=>'apikey', :password=>'......') 56 | [ 57 | service.getDetectFaces('url' => 'https://.....'), 58 | service.detectFaces('images_file' => open('.....jpg','rb')) 59 | ].each do |result| 60 | pp JSON.parse(result.body) 61 | end 62 | 63 | ####Generation of the VisualRecognition service object 64 | 65 | First of all, the instance of the VisualRecognition class has to be generated. 66 | All constructor arguments are passed to the constructor of [RestClient::Resource](http://www.rubydoc.info/gems/rest-client/RestClient/Resource) class except for :version. 67 | Please refer to the document of the rest-client for the details of this hash argument. 68 | 69 | Class name called VisualRecognition is the camel case-ized service name of [Watson API Reference](http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/). 70 | :password is the 'apikey' picked out from environment variable VCAP_SERVICES. 71 | Please refer to '[Viewing Bluemix environment variables](https://console.bluemix.net/docs/services/watson/getting-started-variables.html#vcapServices)' for the details of VCAP_SERVICES. 72 | This gem version no longer supports the authentication mechanism for service instances created before May 23, 2018. 73 | 74 | ####Visual recognition using VisualRecognition#getDetectFaces and VisualRecognition#detectFaces 75 | 76 | Next, by the 'getDetectFaces' and 'detectFaces' method of the VisualRecognition class, we try to recognize examples. 77 | How to set the arguments can be seen at VisualRecognition's [API Reference](https://www.ibm.com/watson/developercloud/visual-recognition/api/v3/curl.html?curl). 78 | 79 | This can be seen by opening the [JSON code of Swagger](https://watson-api-explorer.mybluemix.net/listings/alchemy-language-v1.json). 80 | 81 | The list of the method of the VisualRecognition class can be seen even by using the following script. 82 | 83 | p WatsonAPIClient::VisualRecognition::API['digest'] 84 | 85 | The JSON string is stored in the body of the 'getDetectFaces' and 'detectFaces' method response. 86 | When converting this JSON string to a hash object using JSON.parse method, the result of thesemethods can be used variously by your client programs. 87 | 88 | ###Discovery example 89 | 90 | Last, let's use 'Discovery' service. 91 | 92 | service = WatsonAPIClient::Discovery.new(:version=>'2018-08-01', :user=>".....", :password=>".....") 93 | 94 | result = service.listEnvironments() 95 | pp JSON.parse(result.body) 96 | 97 | result = service.updateEnvironment( 98 | 'environment_id' => '.......', 99 | 'body' => JSON.generate({'name' => 'Tutorial', 'description' => 'description of Tutorial'}) 100 | ) 101 | pp JSON.parse(result.body) 102 | 103 | If the server application is a Ruby on Rails application that require 'watson-api-client', and if it is deployed on the Cloud Foundry, the watson-api-client can read environment variable VCAP_SERVICES directly. In this case, the specification of :user and :password are omissible. 104 | 105 | ###Natural Language Classifier example 106 | 107 | Please see [examples/NaturalLanguageClassifier/README.md](https://github.com/suchowan/watson-api-client/tree/master/examples/NaturalLanguageClassifier/README.md). 108 | 109 | 110 | Additional note 111 | ------- 112 | At present this gem is an alpha version and only the normal behavior of a few services are confirmed. 113 | It is welcome when you can cooperate with the confirmation of other various functions. 114 | 115 | IBM announces that the Watson API Explorer will be removed on [October 31, 2018](https://watson-api-explorer.ng.bluemix.net/). 116 | Therefore, the life span of this gem version is about one month. Please understand this situation before using this gem veresion. 117 | 118 | Credits 119 | ------- 120 | Copyright (c) 2015-2018 [Takashi SUGA](http://hosi.org/TakashiSuga.ttl) 121 | 122 | 123 | Legal 124 | ------- 125 | The watson-api-client is released under the MIT license, see [LICENSE](https://github.com/suchowan/watson-api-client/blob/master/LICENSE) for details. 126 | 127 | IBM Watson™ and IBM Bluemix™ are trade marks of the IBM corporation. 128 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /examples/NaturalLanguageClassifier/README.md: -------------------------------------------------------------------------------- 1 | Natural Language Classifier example 2 | =================================== 3 | 4 | 5 | 1.Preparation 6 | ----------- 7 | 8 | ###VCAP_SERVICES 9 | 10 | Confirm that the Bluemix environment variable [VCAP_SERVICES](http://www.ibm.com/watson/developercloud/doc/getting_started/gs-variables.shtml#vcapServices) is set. 11 | 12 | Otherwise, you should specify :user and :password parameters for each WatsonAPIClient::NaturalLanguageClassifier#new method call in all example scripts. 13 | 14 | ###Example dataset 15 | 16 | Download the example dataset archive from [here](https://www.dropbox.com/sh/h2u6irutgbgvm9r/AAA9GsagC2vYlWPgOIEj-kHZa?dl=0) and extract it to examples/NaturalLanguageClassifier/blog_text/. 17 | 18 | 19 | 2.Training 20 | -------- 21 | 22 | ###Generate Natural Language Classifier object 23 | 24 | ``` 25 | (Example) $ ruby train.rb 2014 2015 26 | ``` 27 | 28 | At first, articles of year 2014 and 2015 are picked out from the dataset, and gathered in train.csv. 29 | 30 | Next, an object of NaturalLanguageClassifier is generated and trained by this train.csv. 31 | 32 | When all the arguments such as 2014 or 2015 are omitted, the train.csv, which already exists, is used for training as it is. 33 | 34 | ###Check Natural Language Classifier object status 35 | 36 | ``` 37 | $ ruby classify.rb 38 | ``` 39 | 40 | When classify.rb is called without arguments, the status of the generated classifier object is retrieved. 41 | 42 | Please wait a moment until its status will be 'Available'. 43 | 44 | 45 | 3.Classification 46 | -------------- 47 | 48 | ``` 49 | (Example) $ ruby classify.rb '2016/08/*' 50 | ``` 51 | 52 | At this example, articles in August, 2016 are picked out from the dataset, and their themes are classified as follows by the classifier object which has been trained. 53 | 54 | ``` 55 | "top_class"=>"こよみ", 56 | "classes"=> 57 | [{"class_name"=>"こよみ", "confidence"=>0.4464514057553849}, 58 | {"class_name"=>"雑記", "confidence"=>0.31750749975306036}, 59 | ... 60 | ``` 61 | 62 | 63 | 4.Natural Language Classifier object deletion 64 | ------------------------------------------- 65 | 66 | ``` 67 | $ ruby delete.rb 68 | ``` 69 | 70 | All the objects that their name are "Blog thema" are deleted. 71 | 72 | When classifier_id is specified as an argument, only the object with the specified classifier_id is deleted. 73 | 74 | 75 | 5.Note 76 | ---- 77 | 78 | According to ['Using your own data to train the Natural Language Classifier'](http://www.ibm.com/watson/developercloud/doc/nl-classifier/data_format.shtml), the maximum total length of a text value is 1024 characters. 79 | 80 | However, in the case of multi-byte characters, more limits seem to be severe. 81 | 82 | Even if the number of characters is within 1024, when the number of bytes exceeds 1200 or 1300, 'Bad Request' has happened by classification processing. 83 | 84 | -------------------------------------------------------------------------------- /examples/NaturalLanguageClassifier/classify.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | require 'pp' 3 | require 'watson-api-client' 4 | 5 | Encoding.default_external = 'UTF-8' 6 | Encoding.default_internal = 'UTF-8' 7 | 8 | service = WatsonAPIClient::NaturalLanguageClassifier.new 9 | JSON.parse(service.getClassifiers.body).first[1].each do |classifier| 10 | next unless classifier['name'] == 'Blog thema' 11 | if ARGV.empty? 12 | pp JSON.parse(service.getStatus(classifier_id:classifier['classifier_id']).body) 13 | else 14 | Dir.glob('blog_text/'+ARGV[0]+'.txt') do |path| 15 | begin 16 | article = open(path,'r',&:read).split(/$/) 17 | text = article[1..-4].map {|line| line[1..-1].gsub(/<.+?>/,'')}.join("\\n") 18 | text.sub!(/.$/,'') while text.bytesize > 1024 19 | expected = article[-2].gsub(/<.+?>/,'').strip.split(/\s*\/\s*/) 20 | pp [JSON.parse(service.classify_get(classifier_id:classifier['classifier_id'], text:text).body), expected] 21 | rescue => e 22 | pp [e, path, text] 23 | end 24 | end 25 | break 26 | end 27 | end 28 | 29 | -------------------------------------------------------------------------------- /examples/NaturalLanguageClassifier/delete.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | require 'pp' 3 | require 'watson-api-client' 4 | 5 | Encoding.default_external = 'UTF-8' 6 | Encoding.default_internal = 'UTF-8' 7 | 8 | service = WatsonAPIClient::NaturalLanguageClassifier.new 9 | if ARGV.empty? 10 | JSON.parse(service.getClassifiers.body).first[1].each do |classifier| 11 | service.delete(classifier_id:classifier['classifier_id']) if classifier['name'] == 'Blog thema' 12 | end 13 | else 14 | service.delete(classifier_id:ARGV[0]) 15 | end 16 | 17 | -------------------------------------------------------------------------------- /examples/NaturalLanguageClassifier/file2csv.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | require 'fileutils' 3 | require 'csv' 4 | 5 | Encoding.default_external = 'UTF-8' 6 | Encoding.default_internal = 'UTF-8' 7 | 8 | train_csv = CSV.generate do |csv| 9 | ARGV.each do |year| 10 | Dir.glob("blog_text/#{year}/**/*.txt") do |path| 11 | article = open(path, 'r', &:read).split(/$/) 12 | text = article[1..-4].map {|line| line[1..-1].gsub(/<.+?>/,'')}.join("\\n") 13 | text.sub!(/.$/,'') while text.bytesize > 1024 14 | klass = article[-2].gsub(/<.+?>/,'').split(/\s*\/\s*/).last.strip 15 | csv << [text, klass] 16 | end 17 | end 18 | end 19 | 20 | File.open('train.csv', 'w') do |file| 21 | file.write(train_csv) 22 | end 23 | -------------------------------------------------------------------------------- /examples/NaturalLanguageClassifier/train.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | require 'pp' 3 | require 'watson-api-client' 4 | require './file2csv' unless ARGV.empty? 5 | 6 | Encoding.default_external = 'UTF-8' 7 | Encoding.default_internal = 'UTF-8' 8 | 9 | service = WatsonAPIClient::NaturalLanguageClassifier.new 10 | pp JSON.parse(service.create(training_metadata: JSON.generate(language: 'ja', name: 'Blog thema'), 11 | training_data: open('train.csv', 'r')).body) 12 | -------------------------------------------------------------------------------- /lib/watson-api-client.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require 'openssl' 3 | require 'open-uri' 4 | require 'rest-client' 5 | require 'pp' if __FILE__ == $PROGRAM_NAME 6 | 7 | class WatsonAPIClient 8 | 9 | VERSION = '0.8.2' 10 | 11 | class << self 12 | 13 | private 14 | 15 | def retrieve_doc(doc_urls) 16 | apis = {} 17 | 18 | # Watson API Explorer 19 | host = doc_urls[/^https?:\/\/[^\/]+/] 20 | open(doc_urls, Options, &:read).scan(/\s*(.+?)\s*<\/a>/i) do 21 | begin 22 | api = {'path'=>doc_urls + $1, 'title'=>$2.sub(/\s*\(.+?\)$/,'')} 23 | open(api['path'], Options, &:read).scan(/url:\s*'(.+?)'/) do 24 | api['path'] = host + $1 25 | end 26 | apis[api['title']] = api 27 | rescue OpenURI::HTTPError 28 | end 29 | end 30 | 31 | apis 32 | end 33 | 34 | # for Swagger 2.0 35 | def listings(apis) 36 | methods = Hash.new {|h,k| h[k] = {}} 37 | digest = Hash.new {|h,k| h[k] = {}} 38 | apis['paths'].each_pair do |path, operations| 39 | common_parameters = nil 40 | operations.each_pair do |access, operation| 41 | if access == 'parameters' 42 | common_parameters = operation 43 | next 44 | end 45 | body, query, min, max = nil, [], [], [] 46 | if operation['parameters'] 47 | operation['parameters'] += common_parameters if common_parameters 48 | (0...operation['parameters'].size).to_a.reverse.each do |index| 49 | parameter = operation['parameters'][index] 50 | operation['parameters'][index..index] = apis['parameters'][parameter[parameter.keys.first].split('/').last] if parameter.keys.first == '$ref' 51 | end 52 | operation['parameters'].each do |parameter| 53 | param = parameter['name'] 54 | body ||= param if parameter['in'] == 'body' 55 | query << param if parameter['in'] == 'query' 56 | min << param if parameter['required'] 57 | max << param 58 | end 59 | end 60 | access = access.downcase 61 | nickname = (operation['operationId'] || path.gsub(/\/\{.+?\}/,'').split('/').last) #.sub(/(.)/) {$1.downcase} 62 | [nickname, nickname+'_'+access].each do |name| 63 | methods[name][access] = {'path'=>path, 'operation'=>operation, 'body'=>body, 'query'=>query, 'min'=>min, 'max'=>max, 'consumes'=>operation['consumes']} 64 | end 65 | digest[nickname][access] = {'path'=>path, 'summary'=>operation['summary']} 66 | end 67 | end 68 | {'apis'=>apis, 'methods'=>methods, 'digest'=>digest} 69 | end 70 | end 71 | 72 | api_docs = { 73 | :gateway => 'https://gateway.watsonplatform.net', 74 | :doc_base => 'https://watson-api-explorer.mybluemix.net/', 75 | :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE 76 | } 77 | JSON.parse(ENV['WATSON_API_DOCS'] || '{}').each_pair do |key, value| 78 | api_docs[key.to_sym] = value 79 | end 80 | doc_urls = api_docs.delete(:doc_base) 81 | Gateways = api_docs.delete(:gateway) 82 | Options = api_docs 83 | Services = JSON.parse(ENV['VCAP_SERVICES'] || '{}') 84 | DefaultParams = {:user=>'username', :password=>'password'} 85 | AvailableAPIs = [] 86 | 87 | retrieve_doc(doc_urls).each_value do |list| 88 | AvailableAPIs << list['title'].gsub(/\s+(.)/) {$1.upcase} 89 | env = list['title'].gsub(/\s+/,'_').downcase 90 | module_eval %Q{ 91 | class #{list['title'].gsub(/\s+(.)/) {$1.upcase}} < WatsonAPIClient 92 | Service = WatsonAPIClient::Services['#{env}'] 93 | RawDoc = "#{list['path']}" 94 | 95 | class << self 96 | alias :_const_missing :const_missing 97 | 98 | def const_missing(constant) 99 | if constant == :API 100 | const_set(:API, listings(JSON.parse(open(RawDoc, WatsonAPIClient::Options, &:read)))) 101 | else 102 | _const_missing(constant) 103 | end 104 | end 105 | end 106 | pp [self, 'See ' + RawDoc, API['digest']] if '#{__FILE__}' == '#{$PROGRAM_NAME}' 107 | end 108 | } 109 | end 110 | 111 | # All subclass constructors use following hash parameter - 112 | # 113 | # @param [Hash] options See following.. 114 | # @option options [String] :url API URL (default: the url described in listings or VCAP_SERVICES) 115 | # @option options [String] :user USER ID (default: the username described in VCAP_SERVICES) 116 | # @option options [String] :password USER Password (default: the password described in VCAP_SERVICES) 117 | # @option options [String] :apikey or :api_key API key for the Alchemy API (default: the apikey or api_key described in VCAP_SERVICES) 118 | # @option options [String] :version The release date of the version of the Alchemy API. 119 | # @option options [Object] other_options Other options are passed to RestClient::Resource.new[http://www.rubydoc.info/gems/rest-client/RestClient/Resource] as it is. 120 | # 121 | # @note VCAP_SERVICES[http://www.ibm.com/watson/developercloud/doc/getting_started/gs-variables.shtml#vcapServices] is IBM Bluemix™ environment variable. 122 | # 123 | def initialize(options={}) 124 | define_api_methods 125 | set_variables(options) 126 | @url ||= Gateways + self.class::API['apis']['basePath'] 127 | @options = {} 128 | self.class.superclass::DefaultParams.each_pair do |sym, key| 129 | @options[sym] = @credential[key] if @credential.key?(key) 130 | end 131 | @options.update(options) 132 | @service = RestClient::Resource.new(@url, @options) 133 | end 134 | 135 | private 136 | 137 | def define_api_methods 138 | self.class::API['methods'].each_pair do |method, definition| 139 | self.class.module_eval %Q{define_method("#{method}", 140 | Proc.new {|options={}| 141 | begin 142 | rest_access_#{definition.keys.size > 1 ? 'auto_detect' : 143 | definition[definition.keys.first]['body'] ? 'with_body' : 144 | 'without_body' }("#{method}", options.dup) 145 | rescue RestClient::ExceptionWithResponse => error 146 | STDERR.puts ["Failed method: #{self.class}##{method}", options] 147 | raise error 148 | end 149 | } 150 | )} unless respond_to?(method) 151 | end 152 | end 153 | 154 | def set_variables(options) 155 | @credential = self.class::Service ? self.class::Service.first['credentials'] : {} 156 | if options.key?(:url) 157 | @url = options.delete(:url) 158 | elsif @credential.key?('url') 159 | @url = @credential['url'] 160 | end 161 | end 162 | 163 | def rest_access_auto_detect(method, options) 164 | definition = self.class::API['methods'][method.to_s] 165 | options[:access] ||= select_access(definition, options) 166 | definition[options[:access]]['body'] ? 167 | rest_access_with_body(method, options) : 168 | rest_access_without_body(method, options) 169 | end 170 | 171 | def rest_access_without_body(method, options) 172 | path, access = swagger_info(method, options) 173 | options = {:params => options} if access == 'get' 174 | @service[path].send(access, options) 175 | end 176 | 177 | def rest_access_with_body(method, options) 178 | path, access, spec = swagger_info(method, options) 179 | body = options.delete(spec['body']) 180 | @service[path].send(access, body, options) 181 | end 182 | 183 | def select_access(definition, options) 184 | definition.keys.reverse.each do |access| 185 | spec = definition[access] 186 | keys = options.keys.map {|key| key.to_s} 187 | return access if (keys - spec['max']).empty? && (spec['min'] - keys).empty? 188 | end 189 | raise ArgumentError, "Cannot select the suitable access method from '#{definition.keys.join(', ')}', see #{self.class::RawDoc}." 190 | end 191 | 192 | def swagger_info(method, options) 193 | definition = self.class::API['methods'][method.to_s] 194 | access = (options.delete(:access) || definition.keys.first).downcase 195 | spec = definition[access] 196 | options.keys.each do |key| 197 | options[key.to_s] = options.delete(key) if key.kind_of?(Symbol) 198 | end 199 | (spec['min'] - options.keys).each do |key| 200 | options[key.to_s] = @options[key.to_sym] if @options.include?(key.to_sym) 201 | end 202 | lacked = spec['min'] - options.keys 203 | extra = options.keys - spec['max'] 204 | raise ArgumentError, "Lacked parameter(s) : '#{lacked.join(', ')}', see #{self.class::RawDoc}." unless lacked.empty? 205 | raise ArgumentError, "Extra parameter(s) : '#{extra.join(', ')}', see #{self.class::RawDoc}." unless extra.empty? 206 | query = {} 207 | spec['query'].each do |param| 208 | query[param] = options.delete(param) if options.key?(param) 209 | end 210 | options[:content_type] = spec['consumes'].first if spec['consumes'].kind_of?(Array) && spec['consumes'].length == 1 211 | path = spec['path'].gsub(/\{(.+?)\}/) {options.delete($1)} 212 | path += '?' + URI.encode_www_form(query) unless query.empty? 213 | [path, access, spec] 214 | end 215 | end 216 | -------------------------------------------------------------------------------- /watson-api-client.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path('../lib', __FILE__) 3 | require 'watson-api-client' 4 | 5 | Gem::Specification.new do |s| 6 | s.name = 'watson-api-client' 7 | s.version = WatsonAPIClient::VERSION 8 | s.authors = ['Takashi SUGA'] 9 | s.email = ['suchowan@box.email.ne.jp'] 10 | s.homepage = 'https://github.com/suchowan/watson-api-client' 11 | s.license = 'MIT' 12 | s.summary = %q{An IBM Watson™ API client} 13 | s.description = %q{The watson-api-client is a gem to use REST API on the IBM Watson™ Developer Cloud. It wraps the rest-client REST API using Swagger documents retrievable from the Watson API Reference.} 14 | 15 | s.files = `git ls-files`.split("\n") 16 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 17 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 18 | s.require_paths = ['lib'] 19 | s.required_ruby_version = '>= 1.9.3' 20 | 21 | # specify any dependencies here; for example: 22 | # s.add_development_dependency 'rspec' 23 | s.add_runtime_dependency 'rest-client' 24 | end 25 | --------------------------------------------------------------------------------