wordnik 4.06.05 → 4.06.06

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.rspec +1 -0
  2. data/Gemfile.lock +22 -16
  3. data/Rakefile +29 -166
  4. data/api_docs/account.json +1 -1
  5. data/api_docs/analytics.json +1 -0
  6. data/api_docs/corpus.json +1 -1
  7. data/api_docs/document.json +1 -1
  8. data/api_docs/partner.json +1 -0
  9. data/api_docs/partners.json +1 -1
  10. data/api_docs/suggest.json +1 -0
  11. data/api_docs/system.json +1 -0
  12. data/api_docs/tag.json +1 -1
  13. data/api_docs/user.json +1 -1
  14. data/api_docs/users.json +1 -1
  15. data/api_docs/word.json +1 -1
  16. data/api_docs/wordList.json +1 -1
  17. data/api_docs/wordLists.json +1 -1
  18. data/api_docs/words.json +1 -1
  19. data/lib/wordnik.rb +58 -17
  20. data/lib/wordnik/configuration.rb +21 -6
  21. data/lib/wordnik/operation.rb +3 -2
  22. data/lib/wordnik/operation_parameter.rb +4 -6
  23. data/lib/wordnik/request.rb +53 -53
  24. data/lib/wordnik/resource.rb +68 -3
  25. data/lib/wordnik/resource_modules/account.rb +0 -26
  26. data/lib/wordnik/resource_modules/analytics.rb +89 -0
  27. data/lib/wordnik/resource_modules/corpus.rb +26 -26
  28. data/lib/wordnik/resource_modules/document.rb +0 -26
  29. data/lib/wordnik/resource_modules/partner.rb +140 -0
  30. data/lib/wordnik/resource_modules/partners.rb +0 -26
  31. data/lib/wordnik/resource_modules/suggest.rb +33 -0
  32. data/lib/wordnik/resource_modules/system.rb +192 -0
  33. data/lib/wordnik/resource_modules/tag.rb +0 -26
  34. data/lib/wordnik/resource_modules/user.rb +0 -26
  35. data/lib/wordnik/resource_modules/users.rb +12 -38
  36. data/lib/wordnik/resource_modules/word.rb +23 -49
  37. data/lib/wordnik/resource_modules/word_list.rb +0 -26
  38. data/lib/wordnik/resource_modules/word_lists.rb +0 -26
  39. data/lib/wordnik/resource_modules/words.rb +0 -26
  40. data/lib/wordnik/response.rb +3 -5
  41. data/lib/wordnik/version.rb +1 -1
  42. data/spec/endpoint_spec.rb +2 -5
  43. data/spec/operation_parameter_spec.rb +32 -11
  44. data/spec/operation_spec.rb +2 -5
  45. data/spec/request_spec.rb +9 -30
  46. data/spec/resource_spec.rb +7 -7
  47. data/spec/response_spec.rb +13 -19
  48. data/spec/spec_helper.rb +14 -2
  49. data/spec/vcr/crazier_json_request.yml +31 -0
  50. data/spec/vcr/default_response.yml +25 -0
  51. data/spec/vcr/get_word_dynamo.yml +33 -0
  52. data/spec/vcr/unauthorized_response.yml +25 -0
  53. data/spec/vcr/wordnik_authenticate.yml +31 -0
  54. data/spec/vcr/wordnik_authenticate_fail.yml +172 -0
  55. data/spec/vcr/xml_response_request.yml +25 -0
  56. data/spec/wordnik_spec.rb +68 -17
  57. data/wordnik.gemspec +2 -0
  58. metadata +48 -5
@@ -1,6 +1,7 @@
1
1
  module Wordnik
2
2
 
3
3
  class Configuration
4
+ require 'wordnik/version'
4
5
 
5
6
  # Wordnik credentials
6
7
  attr_accessor :api_key
@@ -18,23 +19,37 @@ module Wordnik
18
19
  attr_accessor :resource_names
19
20
 
20
21
  # The URL of the API server
21
- attr_accessor :base_uri
22
+ attr_accessor :scheme
23
+ attr_accessor :host
24
+ attr_accessor :base_path
25
+
26
+ attr_accessor :user_agent
22
27
 
23
28
  # Defaults go in here..
24
29
  def initialize
25
30
  @response_format = :json
26
- @base_uri = 'api.wordnik.com/v4'
27
-
31
+ @scheme = 'http'
32
+ @host = 'api.wordnik.com'
33
+ @base_path = '/v4'
34
+ @user_agent = "ruby-#{Wordnik::VERSION}"
28
35
  # Build the default set of resource names from the filenames of the API documentation
29
36
  begin
30
37
  api_docs_path = File.join(File.dirname(__FILE__), "../../api_docs")
31
38
  @resource_names = `find #{api_docs_path} -name '*.json'`.split("\n").map {|f| f.split("/").last.sub('.json', '') }
39
+ true
32
40
  rescue
33
41
  raise "Problem loading the resource files in ./api_docs/"
34
- end
35
-
42
+ end
43
+ end
44
+
45
+ def base_url
46
+ Addressable::URI.new(
47
+ :scheme => self.scheme,
48
+ :host => self.host,
49
+ :path => self.base_path
50
+ )
36
51
  end
37
52
 
38
53
  end
39
54
 
40
- end
55
+ end
@@ -6,7 +6,8 @@ module Wordnik
6
6
  include ActiveModel::Conversion
7
7
  extend ActiveModel::Naming
8
8
 
9
- attr_accessor :endpoint, :http_method, :summary, :notes, :parameters, :response, :open, :nickname, :deprecated, :category, :suggested_name
9
+ attr_accessor :endpoint, :http_method, :summary, :notes, :parameters, :response, :open,
10
+ :nickname, :deprecated, :category, :error_responses, :response_class
10
11
 
11
12
  validates_presence_of :endpoint, :http_method, :summary, :notes, :parameters, :response, :open
12
13
 
@@ -29,7 +30,7 @@ module Wordnik
29
30
  self.parameters = []
30
31
  end
31
32
 
32
- self.nickname = self.suggested_name.underscore
33
+ self.nickname = self.nickname.underscore
33
34
  end
34
35
 
35
36
  # A globally unique identifier for the operation
@@ -6,7 +6,7 @@ module Wordnik
6
6
  include ActiveModel::Conversion
7
7
  extend ActiveModel::Naming
8
8
 
9
- attr_accessor :name, :description, :required, :param_type, :default_value, :allowable_values, :param_access, :internal_description, :wrapper_name, :data_type
9
+ attr_accessor :name, :description, :required, :param_type, :default_value, :allowable_values, :param_access, :internal_description, :wrapper_name, :data_type, :allow_multiple
10
10
 
11
11
  def initialize(attributes = {})
12
12
  attributes.each do |name, value|
@@ -22,17 +22,15 @@ module Wordnik
22
22
  self.name.to_s
23
23
  end
24
24
 
25
- def has_allowable_array?
26
- self.allowable_values.present? && self.allowable_values.include?(",")
27
- end
28
-
29
25
  def required?
30
26
  self.required || self.param_type == "path"
31
27
  end
32
28
 
33
29
  # Is this a required positional param used in a convenience method?
34
30
  def positional?
35
- %w(path body).include?(self.param_type) && self.name.to_sym != :format
31
+ return true if self.param_type == 'body'
32
+ return true if self.param_type == 'path' && self.name.to_s != 'format'
33
+ false
36
34
  end
37
35
 
38
36
  # It's an ActiveModel thing..
@@ -12,30 +12,27 @@ module Wordnik
12
12
 
13
13
  attr_accessor :host, :path, :format, :params, :body, :http_method, :headers
14
14
 
15
- validates_presence_of :host, :path, :format, :http_method
15
+ validates_presence_of :format, :http_method
16
16
 
17
17
  # All requests must have an HTTP method and a path
18
18
  # Optionals parameters are :params, :headers, :body, :format, :host
19
19
  #
20
20
  def initialize(http_method, path, attributes={})
21
- attributes[:format] ||= "json"
22
- attributes[:host] ||= Wordnik.configuration.base_uri
21
+ attributes[:format] ||= Wordnik.configuration.response_format
23
22
  attributes[:params] ||= {}
24
23
 
25
24
  # Set default headers
26
25
  default_headers = {
27
- 'User-Agent' => "Wordnik Ruby Gem #{Wordnik::VERSION}",
28
26
  'Content-Type' => "application/#{attributes[:format].downcase}",
29
27
  :api_key => Wordnik.configuration.api_key
30
28
  }
31
29
 
32
- # If a nil/blank api_key was passed in, remove it from the headers, even if the override value is nil/blank
30
+ # api_key from headers hash trumps the default, even if its value is blank
33
31
  if attributes[:headers].present? && attributes[:headers].has_key?(:api_key)
34
32
  default_headers.delete(:api_key)
35
33
  end
36
34
 
37
- # If nil/blank api_key was passed in in the params, it overrides both the default
38
- # headers and the argument headers
35
+ # api_key from params hash trumps all others (headers and default_headers)
39
36
  if attributes[:params].present? && attributes[:params].has_key?(:api_key)
40
37
  default_headers.delete(:api_key)
41
38
  attributes[:headers].delete(:api_key) if attributes[:headers].present?
@@ -57,18 +54,30 @@ module Wordnik
57
54
  end
58
55
 
59
56
  # Construct a base URL
60
- def url
61
- u = Addressable::URI.new
62
- u.host = self.host.sub(/\/$/, '') # Remove trailing slash
63
- u.path = self.interpreted_path
64
- u.scheme = "http" # For some reason this must be set _after_ host, otherwise Addressable gets upset
65
- u.to_s
57
+ #
58
+ def url(options = {})
59
+ u = Addressable::URI.new(
60
+ :scheme => Wordnik.configuration.scheme,
61
+ :host => Wordnik.configuration.host,
62
+ :path => self.interpreted_path,
63
+ :query => self.query_string.sub(/\?/, '')
64
+ ).to_s
65
+
66
+ # Drop trailing question mark, if present
67
+ u.sub! /\?$/, ''
68
+
69
+ # Obfuscate API key?
70
+ u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated]
71
+
72
+ u
66
73
  end
67
74
 
68
75
  # Iterate over the params hash, injecting any path values into the path string
69
76
  # e.g. /word.{format}/{word}/entries => /word.json/cat/entries
70
77
  def interpreted_path
71
- p = self.path
78
+ p = self.path.dup
79
+
80
+ # Fill in the path params
72
81
  self.params.each_pair do |key, value|
73
82
  p = p.gsub("{#{key}}", value.to_s)
74
83
  end
@@ -80,8 +89,9 @@ module Wordnik
80
89
  p = p.sub(/^(\/?\w+)/, "\\1.#{format}")
81
90
  end
82
91
 
83
- p = p.sub("{format}", self.format)
84
- URI.encode(p)
92
+ p = p.sub("{format}", self.format.to_s)
93
+
94
+ URI.encode [Wordnik.configuration.base_path, p].join("/").gsub(/\/+/, '/')
85
95
  end
86
96
 
87
97
  # Massage the request body into a state of readiness
@@ -97,77 +107,67 @@ module Wordnik
97
107
  @body = value
98
108
  end
99
109
 
110
+ # If body is an object, JSONify it before making the actual request.
111
+ #
100
112
  def outgoing_body
101
- return self.body if self.body.is_a? String
102
- self.body.to_json
113
+ body.is_a?(String) ? body : body.to_json
103
114
  end
104
-
105
- # Iterate over all params,
106
- # .. removing the ones that are part of the path itself.
107
- # .. stringifying values so Addressable doesn't blow up.
108
- # .. obfuscating the API key if needed.
109
- def query_string_params(obfuscated=false)
110
- qsp = {}
115
+
116
+ # Construct a query string from the query-string-type params
117
+ def query_string
118
+
119
+ # Iterate over all params,
120
+ # .. removing the ones that are part of the path itself.
121
+ # .. stringifying values so Addressable doesn't blow up.
122
+ query_values = {}
111
123
  self.params.each_pair do |key, value|
112
124
  next if self.path.include? "{#{key}}" # skip path params
113
125
  next if value.blank? && value.class != FalseClass # skip empties
114
- value = "YOUR_API_KEY" if key.to_sym == :api_key && obfuscated # obscure the API key
115
126
  key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param
116
- qsp[key] = value.to_s
127
+ query_values[key] = value.to_s
117
128
  end
118
- qsp
119
- end
120
-
121
- # Construct a query string from the query-string-type params
122
- def query_string(options={})
123
129
 
124
130
  # We don't want to end up with '?' as our query string
125
131
  # if there aren't really any params
126
- return "" if query_string_params.blank?
127
-
128
- default_options = {:obfuscated => false}
129
- options = default_options.merge(options)
132
+ return "" if query_values.blank?
130
133
 
134
+ # Addressable requires query_values to be set after initialization..
131
135
  qs = Addressable::URI.new
132
- qs.query_values = self.query_string_params(options[:obfuscated])
136
+ qs.query_values = query_values
133
137
  qs.to_s
134
138
  end
135
139
 
136
- # Returns full request URL with query string included
137
- def url_with_query_string(options={})
138
- default_options = {:obfuscated => false}
139
- options = default_options.merge(options)
140
-
141
- [url, query_string(options)].join('')
142
- end
143
-
144
140
  def make
145
141
  response = case self.http_method.to_sym
146
142
  when :get
147
143
  Typhoeus::Request.get(
148
- self.url_with_query_string,
149
- :headers => self.headers.stringify_keys
144
+ self.url,
145
+ :headers => self.headers.stringify_keys,
146
+ :user_agent => Wordnik.configuration.user_agent
150
147
  )
151
148
 
152
149
  when :post
153
150
  Typhoeus::Request.post(
154
- self.url_with_query_string,
151
+ self.url,
155
152
  :body => self.outgoing_body,
156
- :headers => self.headers.stringify_keys
153
+ :headers => self.headers.stringify_keys,
154
+ :user_agent => Wordnik.configuration.user_agent
157
155
  )
158
156
 
159
157
  when :put
160
158
  Typhoeus::Request.put(
161
- self.url_with_query_string,
159
+ self.url,
162
160
  :body => self.outgoing_body,
163
- :headers => self.headers.stringify_keys
161
+ :headers => self.headers.stringify_keys,
162
+ :user_agent => Wordnik.configuration.user_agent
164
163
  )
165
164
 
166
165
  when :delete
167
166
  Typhoeus::Request.delete(
168
- self.url_with_query_string,
167
+ self.url,
169
168
  :body => self.outgoing_body,
170
- :headers => self.headers.stringify_keys
169
+ :headers => self.headers.stringify_keys,
170
+ :user_agent => Wordnik.configuration.user_agent
171
171
  )
172
172
  end
173
173
  Response.new(response)
@@ -22,8 +22,8 @@ module Wordnik
22
22
  end
23
23
 
24
24
  # Generate Endpoint instances from JSON
25
- if self.raw_data['endPoints']
26
- self.endpoints = self.raw_data['endPoints'].map do |endpointData|
25
+ if self.raw_data['apis']
26
+ self.endpoints = self.raw_data['apis'].map do |endpointData|
27
27
  Endpoint.new(self, endpointData)
28
28
  end
29
29
  end
@@ -34,7 +34,72 @@ module Wordnik
34
34
  self.class.send(:require, "wordnik/resource_modules/#{self.name}")
35
35
  self.class.send(:include, "#{self.name.to_s.camelize}Methods".constantize)
36
36
  end
37
-
37
+ end
38
+
39
+ def write_convenience_methods
40
+ return unless endpoints.present?
41
+
42
+ filename = "lib/wordnik/resource_modules/#{name}.rb"
43
+ puts " #{filename}"
44
+ file = File.new(filename, "w")
45
+ lines = []
46
+
47
+ lines << "# HEY HACKER! THIS IS AN AUTO-GENERATED FILE."
48
+ lines << "# So don't bother editing it. To see how it's built, take a look at the Rakefile\n"
49
+
50
+ lines << "module #{name.to_s.camelize}Methods\n"
51
+
52
+ endpoints.each do |endpoint|
53
+ endpoint.operations.each do |operation|
54
+
55
+ next if operation.nickname.blank?
56
+
57
+ # Comment about the operation
58
+ # (Turn newlines into commented newlines)
59
+ lines << " # #{operation.summary.gsub("\n", "\n # ")}" if operation.summary.present?
60
+ lines << " # #{operation.notes.gsub("\n", "\n # ")}" if operation.notes.present?
61
+ lines << " #" if operation.summary.present?
62
+
63
+ # Start writing the method
64
+ lines << " def #{operation.nickname}(#{[operation.positional_parameter_names, '*args'].flatten.join(', ')})"
65
+
66
+ # HTTP Method
67
+ lines << " http_method = :#{operation.http_method}"
68
+
69
+ # Path
70
+ lines << " path = '#{endpoint.path.sub(".{format}", "")}'"
71
+ operation.positional_parameter_names.each do |param|
72
+ # `body` positional params don't get injected into the path will be dealt with separately
73
+ next if param.to_s == 'body'
74
+ lines << " path.sub!('\{#{param}\}', #{param}.to_s)"
75
+ end
76
+
77
+ lines << "\n # Ruby turns all key-value arguments at the end into a single hash"
78
+ lines << " # e.g. Wordnik.word.get_examples('dingo', :limit => 10, :part_of_speech => 'verb')"
79
+ lines << " # becomes {:limit => 10, :part_of_speech => 'verb'}"
80
+ lines << " last_arg = args.pop if args.last.is_a?(Hash)"
81
+ lines << " last_arg = args.pop if args.last.is_a?(Array)"
82
+ lines << " last_arg ||= {}\n"
83
+
84
+ lines << " # Look for a kwarg called :request_only, whose presence indicates"
85
+ lines << " # that we want the request itself back, not the response body"
86
+ lines << " if last_arg.is_a?(Hash) && last_arg[:request_only].present?"
87
+ lines << " request_only = true"
88
+ lines << " last_arg.delete(:request_only)"
89
+ lines << " end\n"
90
+
91
+ lines << " params = last_arg"
92
+ lines << " body ||= {}"
93
+
94
+ lines << " request = Wordnik::Request.new(http_method, path, :params => params, :body => body)"
95
+ lines << " request_only ? request : request.response.body"
96
+ lines << " end\n"
97
+ end
98
+ end
99
+
100
+ lines << "end"
101
+ file.write lines.join("\n")
102
+ file.close
38
103
  end
39
104
 
40
105
  # It's an ActiveModel thing..
@@ -83,32 +83,6 @@ module AccountMethods
83
83
  request_only ? request : request.response.body
84
84
  end
85
85
 
86
- # Returns information about API parameters
87
- #
88
- def get_help(*args)
89
- http_method = :get
90
- path = '/account'
91
-
92
- # Ruby turns all key-value arguments at the end into a single hash
93
- # e.g. Wordnik.word.get_examples('dingo', :limit => 10, :part_of_speech => 'verb')
94
- # becomes {:limit => 10, :part_of_speech => 'verb'}
95
- last_arg = args.pop if args.last.is_a?(Hash)
96
- last_arg = args.pop if args.last.is_a?(Array)
97
- last_arg ||= {}
98
-
99
- # Look for a kwarg called :request_only, whose presence indicates
100
- # that we want the request itself back, not the response body
101
- if last_arg.is_a?(Hash) && last_arg[:request_only].present?
102
- request_only = true
103
- last_arg.delete(:request_only)
104
- end
105
-
106
- params = last_arg
107
- body ||= {}
108
- request = Wordnik::Request.new(http_method, path, :params => params, :body => body)
109
- request_only ? request : request.response.body
110
- end
111
-
112
86
  # Fetches WordList objects for the logged-in user.
113
87
  #
114
88
  def get_word_lists_for_current_user(*args)
@@ -0,0 +1,89 @@
1
+ # HEY HACKER! THIS IS AN AUTO-GENERATED FILE.
2
+ # So don't bother editing it. To see how it's built, take a look at the Rakefile
3
+
4
+ module AnalyticsMethods
5
+
6
+ # Returns top hits over a year, month, week, day or hour
7
+ # If no time resolution parameters are passed, it returns top hits for this week. To fetch top hits for a year, pass only the year. To fetch top hits for a month, pass (year and month). To fetch top hits for a week, pass (year and week). To fetch top hits for a day, pass (year, month and day). To fetch top hits for an hour, pass (year, month, day and hour).
8
+ #
9
+ def get_top_hits(*args)
10
+ http_method = :get
11
+ path = '/analytics/top'
12
+
13
+ # Ruby turns all key-value arguments at the end into a single hash
14
+ # e.g. Wordnik.word.get_examples('dingo', :limit => 10, :part_of_speech => 'verb')
15
+ # becomes {:limit => 10, :part_of_speech => 'verb'}
16
+ last_arg = args.pop if args.last.is_a?(Hash)
17
+ last_arg = args.pop if args.last.is_a?(Array)
18
+ last_arg ||= {}
19
+
20
+ # Look for a kwarg called :request_only, whose presence indicates
21
+ # that we want the request itself back, not the response body
22
+ if last_arg.is_a?(Hash) && last_arg[:request_only].present?
23
+ request_only = true
24
+ last_arg.delete(:request_only)
25
+ end
26
+
27
+ params = last_arg
28
+ body ||= {}
29
+ request = Wordnik::Request.new(http_method, path, :params => params, :body => body)
30
+ request_only ? request : request.response.body
31
+ end
32
+
33
+ # Returns words which were trending on a given week or month
34
+ # If no time resolution parameters are passed, it returns trending hits for this week.
35
+ # To fetch trending hits for a month, pass (year and month). To fetch trending hits for a week, pass (year and week).
36
+ #
37
+ def get_trending_hits(*args)
38
+ http_method = :get
39
+ path = '/analytics/trending'
40
+
41
+ # Ruby turns all key-value arguments at the end into a single hash
42
+ # e.g. Wordnik.word.get_examples('dingo', :limit => 10, :part_of_speech => 'verb')
43
+ # becomes {:limit => 10, :part_of_speech => 'verb'}
44
+ last_arg = args.pop if args.last.is_a?(Hash)
45
+ last_arg = args.pop if args.last.is_a?(Array)
46
+ last_arg ||= {}
47
+
48
+ # Look for a kwarg called :request_only, whose presence indicates
49
+ # that we want the request itself back, not the response body
50
+ if last_arg.is_a?(Hash) && last_arg[:request_only].present?
51
+ request_only = true
52
+ last_arg.delete(:request_only)
53
+ end
54
+
55
+ params = last_arg
56
+ body ||= {}
57
+ request = Wordnik::Request.new(http_method, path, :params => params, :body => body)
58
+ request_only ? request : request.response.body
59
+ end
60
+
61
+ # Returns hits a word received in a given year, month, week or day
62
+ # If no time resolution parameters are passed, it returns hits the word received this week. To fetch word hits for a year, pass only the year. To fetch word hits for a month, pass (year and month). To fetch word hits for a week, pass (year and week). To fetch word hits for a day, pass (year, month and day)
63
+ #
64
+ def get_word_hits(word, *args)
65
+ http_method = :get
66
+ path = '/analytics/word/{word}'
67
+ path.sub!('{word}', word.to_s)
68
+
69
+ # Ruby turns all key-value arguments at the end into a single hash
70
+ # e.g. Wordnik.word.get_examples('dingo', :limit => 10, :part_of_speech => 'verb')
71
+ # becomes {:limit => 10, :part_of_speech => 'verb'}
72
+ last_arg = args.pop if args.last.is_a?(Hash)
73
+ last_arg = args.pop if args.last.is_a?(Array)
74
+ last_arg ||= {}
75
+
76
+ # Look for a kwarg called :request_only, whose presence indicates
77
+ # that we want the request itself back, not the response body
78
+ if last_arg.is_a?(Hash) && last_arg[:request_only].present?
79
+ request_only = true
80
+ last_arg.delete(:request_only)
81
+ end
82
+
83
+ params = last_arg
84
+ body ||= {}
85
+ request = Wordnik::Request.new(http_method, path, :params => params, :body => body)
86
+ request_only ? request : request.response.body
87
+ end
88
+
89
+ end