wordnik 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in wordnik.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ wordnik (0.0.1)
5
+ activemodel (= 3.0.3)
6
+ addressable (= 2.2.4)
7
+ htmlentities (= 4.2.4)
8
+ json (= 1.4.6)
9
+ nokogiri (= 1.4.4)
10
+ typhoeus (= 0.2.1)
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ activemodel (3.0.3)
16
+ activesupport (= 3.0.3)
17
+ builder (~> 2.1.2)
18
+ i18n (~> 0.4)
19
+ activesupport (3.0.3)
20
+ addressable (2.2.4)
21
+ builder (2.1.2)
22
+ crack (0.1.8)
23
+ diff-lcs (1.1.2)
24
+ htmlentities (4.2.4)
25
+ i18n (0.5.0)
26
+ json (1.4.6)
27
+ mime-types (1.16)
28
+ nokogiri (1.4.4)
29
+ rspec (2.4.0)
30
+ rspec-core (~> 2.4.0)
31
+ rspec-expectations (~> 2.4.0)
32
+ rspec-mocks (~> 2.4.0)
33
+ rspec-core (2.4.0)
34
+ rspec-expectations (2.4.0)
35
+ diff-lcs (~> 1.1.2)
36
+ rspec-mocks (2.4.0)
37
+ typhoeus (0.2.1)
38
+ mime-types
39
+ vcr (1.5.1)
40
+ webmock (1.6.2)
41
+ addressable (>= 2.2.2)
42
+ crack (>= 0.1.7)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ activemodel (= 3.0.3)
49
+ addressable (= 2.2.4)
50
+ htmlentities (= 4.2.4)
51
+ json (= 1.4.6)
52
+ nokogiri (= 1.4.4)
53
+ rspec (= 2.4.0)
54
+ typhoeus (= 0.2.1)
55
+ vcr (= 1.5.1)
56
+ webmock (= 1.6.2)
57
+ wordnik!
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new('spec')
7
+
8
+ # If you want to make this the default task
9
+ task :default => :spec
data/lib/wordnik.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'wordnik/endpoint'
2
+ require 'wordnik/operation'
3
+ require 'wordnik/operation_parameter'
4
+ require 'wordnik/request'
5
+ require 'wordnik/resource'
6
+ require 'wordnik/response'
7
+ require 'wordnik/configuration'
8
+
9
+ module Wordnik
10
+
11
+ API_VERSION = "4.01.61"
12
+
13
+ class << self
14
+
15
+ # A Wordnik configuration object. Must act like a hash and return sensible
16
+ # values for all Wordnik configuration options. See Wordnik::Configuration.
17
+ attr_accessor :configuration
18
+
19
+ # Call this method to modify defaults in your initializers.
20
+ #
21
+ # @example
22
+ # Wordnik.configure do |config|
23
+ # config.api_key = '1234567890abcdef'
24
+ # config.response_format = :json
25
+ # end
26
+ def configure
27
+ self.configuration ||= Configuration.new
28
+ yield(configuration) if block_given?
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,21 @@
1
+ module Wordnik
2
+
3
+ class Configuration
4
+
5
+ # The API key for your project, found on the project edit form.
6
+ attr_accessor :api_key
7
+
8
+ # Response format can be :json (default) or :xml
9
+ attr_accessor :response_format
10
+
11
+ # The URL of the API server
12
+ attr_accessor :base_uri
13
+
14
+ def initialize
15
+ @response_format = :json
16
+ @base_uri = 'beta.wordnik.com/v4'
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,32 @@
1
+ # To jog the memory: Resource > Endpoint > Operation > OperationParameter
2
+ require 'active_model'
3
+
4
+ class Endpoint
5
+
6
+ include ActiveModel::Validations
7
+ include ActiveModel::Conversion
8
+ extend ActiveModel::Naming
9
+
10
+ attr_accessor :path, :description, :operations
11
+
12
+ validates_presence_of :path, :description, :operations
13
+
14
+ def initialize(attributes = {})
15
+ attributes.each do |name, value|
16
+ send("#{name.to_s.underscore.to_sym}=", value)
17
+ end
18
+
19
+ # Generate Operations instances from JSON
20
+ if self.operations
21
+ self.operations = self.operations.map do |operationData|
22
+ Operation.new(operationData)
23
+ end
24
+ end
25
+ end
26
+
27
+ # It's an ActiveModel thing..
28
+ def persisted?
29
+ false
30
+ end
31
+
32
+ end
@@ -0,0 +1,42 @@
1
+ # To jog the memory: Resource > Endpoint > Operation > OperationParameter
2
+
3
+ class Operation
4
+ include ActiveModel::Validations
5
+ include ActiveModel::Conversion
6
+ extend ActiveModel::Naming
7
+
8
+ attr_accessor :http_method, :summary, :notes, :parameters, :response, :open
9
+
10
+ validates_presence_of :http_method, :summary, :notes, :parameters, :response, :open
11
+
12
+ def initialize(attributes = {})
13
+ attributes.each do |name, value|
14
+ send("#{name.to_s.underscore.to_sym}=", value)
15
+ end
16
+
17
+ self.http_method = self.http_method.to_s.downcase
18
+
19
+ # Generate OperationParameter instances from JSON
20
+ if self.parameters
21
+ self.parameters = self.parameters.map do |parameterData|
22
+ OperationParameter.new(parameterData)
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ def get?
29
+ self.http_method.downcase == "get"
30
+ end
31
+
32
+ # Can this operation be run in the sandbox?
33
+ def sandboxable?
34
+ self.get?
35
+ end
36
+
37
+ # It's an ActiveModel thing..
38
+ def persisted?
39
+ false
40
+ end
41
+
42
+ end
@@ -0,0 +1,36 @@
1
+ # To jog the memory: Resource > Endpoint > Operation > OperationParameter
2
+
3
+ class OperationParameter
4
+ include ActiveModel::Validations
5
+ include ActiveModel::Conversion
6
+ extend ActiveModel::Naming
7
+
8
+ attr_accessor :name, :description, :required, :param_type, :default_value, :allowable_values
9
+
10
+ validates_presence_of :name, :description, :required, :param_type, :default_value, :allowable_values
11
+
12
+ def initialize(attributes = {})
13
+ attributes.each do |name, value|
14
+ send("#{name.to_s.underscore.to_sym}=", value)
15
+ end
16
+ end
17
+
18
+ def human_name
19
+ return "request body" if self.param_type == 'body'
20
+ self.name
21
+ end
22
+
23
+ def has_allowable_array?
24
+ self.allowable_values.present? && self.allowable_values.include?(",")
25
+ end
26
+
27
+ def required?
28
+ self.required
29
+ end
30
+
31
+ # It's an ActiveModel thing..
32
+ def persisted?
33
+ false
34
+ end
35
+
36
+ end
@@ -0,0 +1,159 @@
1
+ class Request
2
+ require 'uri'
3
+ require 'addressable/uri'
4
+ require 'typhoeus'
5
+ include ActiveModel::Validations
6
+ include ActiveModel::Conversion
7
+ extend ActiveModel::Naming
8
+
9
+ attr_accessor :host, :port, :path, :format, :params, :body, :http_method, :headers
10
+
11
+ validates_presence_of :host, :path, :format, :http_method
12
+
13
+ def initialize(http_method, path, attributes={})
14
+ attributes[:format] ||= "json"
15
+ attributes[:host] ||= Wordnik.configuration.base_uri
16
+ attributes[:params] ||= {}
17
+
18
+ # Set default headers, but allow them to be overridden
19
+ default_headers = {
20
+ 'Content-Type' => "application/#{attributes[:format].downcase}",
21
+ }
22
+ attributes[:headers] = default_headers.merge(attributes[:headers] || {})
23
+
24
+ self.http_method = http_method.to_sym
25
+ self.path = path
26
+ attributes.each do |name, value|
27
+ send("#{name.to_s.underscore.to_sym}=", value)
28
+ end
29
+ end
30
+
31
+ # Construct a base URL
32
+ def url
33
+ u = Addressable::URI.new
34
+ u.host = self.host.sub(/\/$/, '')
35
+ u.port = self.port if self.port.present?
36
+ u.path = self.interpreted_path
37
+ u.scheme = "http" # For some reason this must be set _after_ host, otherwise Addressable gets upset
38
+ u.to_s
39
+ end
40
+
41
+ # Iterate over the params hash, injecting any path values into the path string
42
+ # e.g. /word.{format}/{word}/entries => /word.json/cat/entries
43
+ def interpreted_path
44
+ p = self.path
45
+ self.params.each_pair do |key, value|
46
+ p = p.gsub("{#{key}}", value.to_s)
47
+ end
48
+
49
+ # Stick a .{format} placeholder into the path if there isn't
50
+ # one already or an actual format like json or xml
51
+ # e.g. /words/blah => /words.{format}/blah
52
+ unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
53
+ p = p.sub(/^(\/?\w+)/, "\\1.#{format}")
54
+ end
55
+
56
+ p = p.sub("{format}", self.format)
57
+ URI.encode(p)
58
+ end
59
+
60
+ def interpreted_body
61
+ return unless self.body.present?
62
+ return self.body.to_json if self.body.is_a?(Hash)
63
+ self.body
64
+ end
65
+
66
+ # Iterate over all params,
67
+ # .. removing the ones that are part of the path itself.
68
+ # .. stringifying values so Addressable doesn't blow up.
69
+ # .. obfuscating the API key if needed.
70
+ def query_string_params(obfuscated=false)
71
+ qsp = {}
72
+ self.params.each_pair do |key, value|
73
+ next if self.path.include? "{#{key}}"
74
+ next if value.blank?
75
+ value = "YOUR_API_KEY" if key.to_sym == :api_key && obfuscated
76
+ qsp[key] = value.to_s
77
+ end
78
+ qsp
79
+ end
80
+
81
+ # Construct a query string from the query-string-type params
82
+ def query_string(options={})
83
+
84
+ # We don't want to end up with '?' as our query string
85
+ # if there aren't really any params
86
+ return "" if query_string_params.blank?
87
+
88
+ default_options = {:obfuscated => false}
89
+ options = default_options.merge(options)
90
+
91
+ qs = Addressable::URI.new
92
+ qs.query_values = self.query_string_params(options[:obfuscated])
93
+ qs.to_s
94
+ end
95
+
96
+ # Returns full request URL with query string included
97
+ def url_with_query_string(options={})
98
+ default_options = {:obfuscated => false}
99
+ options = default_options.merge(options)
100
+
101
+ [url, query_string(options)].join('')
102
+ end
103
+
104
+ def make
105
+ response = case self.http_method.to_sym
106
+ when :get
107
+ Typhoeus::Request.get(
108
+ self.url_with_query_string,
109
+ :headers => self.headers.stringify_keys
110
+ )
111
+
112
+ when :post
113
+ Typhoeus::Request.post(
114
+ self.url_with_query_string,
115
+ :body => self.interpreted_body,
116
+ :headers => self.headers.stringify_keys
117
+ )
118
+
119
+ when :put
120
+ Typhoeus::Request.put(
121
+ self.url_with_query_string,
122
+ :body => self.interpreted_body,
123
+ :headers => self.headers.stringify_keys
124
+ )
125
+
126
+ when :delete
127
+ Typhoeus::Request.delete(
128
+ self.url_with_query_string,
129
+ :body => self.interpreted_body,
130
+ :headers => self.headers.stringify_keys
131
+ )
132
+ end
133
+
134
+ @response_obj = Response.new(response)
135
+ end
136
+
137
+ # If the request has been made, return the existing response
138
+ # If not, make the request and return the response
139
+ def response
140
+ @response_obj || self.make
141
+ end
142
+
143
+ def response_code_pretty
144
+ return unless @response.present?
145
+ @response.code.to_s
146
+ end
147
+
148
+ def response_headers_pretty
149
+ return unless @response.present?
150
+ # JSON.pretty_generate(@response.headers).gsub(/\n/, '<br/>').html_safe # <- This was for RestClient
151
+ @response.headers.gsub(/\n/, '<br/>').html_safe # <- This is for Typhoeus
152
+ end
153
+
154
+ # It's an ActiveModel thing..
155
+ def persisted?
156
+ false
157
+ end
158
+
159
+ end
@@ -0,0 +1,50 @@
1
+ # To jog the memory: Resource > Endpoint > Operation > OperationParameter
2
+
3
+ class Resource
4
+
5
+ include ActiveModel::Validations
6
+ include ActiveModel::Conversion
7
+ extend ActiveModel::Naming
8
+
9
+ attr_accessor :name, :raw_data, :endpoints, :models
10
+
11
+ validates_presence_of :name, :raw_data, :endpoints, :models
12
+
13
+ def initialize(attributes = {})
14
+ attributes.each do |name, value|
15
+ send("#{name.to_s.underscore.to_sym}=", value)
16
+ end
17
+
18
+ # Generate Endpoint instances from JSON
19
+ if self.raw_data['endPoints']
20
+ self.endpoints = self.raw_data['endPoints'].map do |endpointData|
21
+ Endpoint.new(endpointData)
22
+ end
23
+ end
24
+ end
25
+
26
+ def operation_nickname_pairs
27
+ return unless self.endpoints.present?
28
+ pairs = {}
29
+ self.endpoints.map do |endpoint|
30
+ endpoint.operations.map do |operation|
31
+ nickname_parts = []
32
+ nickname_parts << operation.http_method
33
+ nickname_parts << endpoint.path.gsub(/\{\w+\}/, "").gsub("/", "_").nix(' ').nix('.').underscore
34
+ nickname = nickname_parts.
35
+ join("_").
36
+ gsub(/_+/, "_").
37
+ gsub("_#{self.name.underscore}", "").
38
+ gsub(/_$/, "")
39
+ pairs[nickname] = "#{operation.http_method.upcase} #{endpoint.path}"
40
+ end
41
+ end
42
+ pairs
43
+ end
44
+
45
+ # It's an ActiveModel thing..
46
+ def persisted?
47
+ false
48
+ end
49
+
50
+ end
@@ -0,0 +1,69 @@
1
+ class Response
2
+ include ActiveModel::Validations
3
+ include ActiveModel::Conversion
4
+ extend ActiveModel::Naming
5
+
6
+ attr_accessor :raw
7
+
8
+ validates_presence_of :raw
9
+
10
+ def initialize(raw)
11
+ self.raw = raw
12
+ end
13
+
14
+ def code
15
+ raw.code
16
+ end
17
+
18
+ # If body is JSON, parse it
19
+ # TODO: If body is XML, parse it
20
+ # Otherwise return raw string
21
+ def body
22
+ JSON.parse(raw.body)
23
+ rescue
24
+ raw.body
25
+ end
26
+
27
+ def headers
28
+ h = {}
29
+ raw.headers_hash.each {|k,v| h[k] = v }
30
+ h
31
+ end
32
+
33
+ # Extract the response format from the header hash
34
+ # e.g. {'Content-Type' => 'application/json'}
35
+ def format
36
+ headers['Content-Type'].split("/").last.to_sym
37
+ end
38
+
39
+ def json?
40
+ format == :json
41
+ end
42
+
43
+ def xml?
44
+ format == :xml
45
+ end
46
+
47
+ def pretty_body
48
+ return unless body.present?
49
+ case format
50
+ when :json
51
+ JSON.pretty_generate(body).gsub(/\n/, '<br/>').html_safe
52
+ when :xml
53
+ xsl = Nokogiri::XSLT(File.open(Rails.root.join("config", "pretty_print.xsl")))
54
+ xml = Nokogiri(body)
55
+ coder = HTMLEntities.new
56
+ coder.encode(xsl.apply_to(xml).to_s)
57
+ end
58
+ end
59
+
60
+ def pretty_headers
61
+ JSON.pretty_generate(headers).gsub(/\n/, '<br/>').html_safe
62
+ end
63
+
64
+ # It's an ActiveModel thing..
65
+ def persisted?
66
+ false
67
+ end
68
+
69
+ end
@@ -0,0 +1,3 @@
1
+ module Wordnik
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Endpoint do
4
+
5
+ before(:each) do
6
+ VCR.use_cassette('words', :record => :new_episodes) do
7
+ @response = Typhoeus::Request.get("http://api.wordnik.com/v4/word.json")
8
+ end
9
+
10
+ @endpoint = Endpoint.new(JSON.parse(@response.body)['endPoints'].first)
11
+ end
12
+
13
+ describe "initialization" do
14
+
15
+ it "successfully initializes" do
16
+ @endpoint.path.should == "/word.{format}/{word}"
17
+ end
18
+
19
+ it "sets operations" do
20
+ @endpoint.operations.class.should == Array
21
+ @endpoint.operations.first.class.should == Operation
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe OperationParameter do
4
+
5
+ before(:each) do
6
+ VCR.use_cassette('words', :record => :new_episodes) do
7
+ @response = Typhoeus::Request.get("http://api.wordnik.com/v4/word.json")
8
+ end
9
+
10
+ @operation_parameter = OperationParameter.new(JSON.parse(@response.body)['endPoints'].first['operations'].first['parameters'].first)
11
+ end
12
+
13
+ describe "initialization" do
14
+
15
+ it "successfully initializes" do
16
+ @operation_parameter.respond_to?(:name).should == true
17
+ @operation_parameter.respond_to?(:description).should == true
18
+ @operation_parameter.respond_to?(:required).should == true
19
+ @operation_parameter.respond_to?(:param_type).should == true
20
+ @operation_parameter.respond_to?(:default_value).should == true
21
+ @operation_parameter.respond_to?(:allowable_values).should == true
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Operation do
4
+
5
+ before(:each) do
6
+ VCR.use_cassette('words', :record => :new_episodes) do
7
+ @response = Typhoeus::Request.get("http://api.wordnik.com/v4/word.json")
8
+ end
9
+
10
+ @operation = Operation.new(JSON.parse(@response.body)['endPoints'].first['operations'].first)
11
+ end
12
+
13
+ describe "initialization" do
14
+
15
+ it "successfully initializes" do
16
+ @operation.summary.should =~ /returns the WordObject/i
17
+ end
18
+
19
+ it "sets parameters" do
20
+ @operation.parameters.class.should == Array
21
+ @operation.parameters.first.class.should == OperationParameter
22
+ end
23
+
24
+ end
25
+
26
+ describe "instance methods" do
27
+ it "knows if its HTTP method is GET" do
28
+ @operation.http_method = "GET"
29
+ @operation.get?.should == true
30
+ @operation.http_method = "POST"
31
+ @operation.get?.should == false
32
+ @operation.http_method = "get"
33
+ @operation.get?.should == true
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ describe Request do
4
+
5
+ before(:each) do
6
+ @default_http_method = :get
7
+ @default_path = "words/fancy"
8
+ @default_params = {
9
+ :params => {:foo => "1", :bar => "2"}
10
+ }
11
+ @request = Request.new(@default_http_method, @default_path, @default_params)
12
+ end
13
+
14
+ describe "initialization" do
15
+ it "sets default response format to json" do
16
+ @request.format.should == "json"
17
+ end
18
+
19
+ it "sets get default host from Wordnik.configuration" do
20
+ @request.host.should == Wordnik.configuration.base_uri
21
+ end
22
+
23
+ end
24
+
25
+ describe "attr_accessors" do
26
+
27
+ it "has working attributes" do
28
+ @request.host.should == Wordnik.configuration.base_uri
29
+ @request.path.should == "words/fancy"
30
+ end
31
+
32
+ it "allows attributes to be overwritten" do
33
+ @request.http_method.should == :get
34
+ @request.http_method = "post"
35
+ @request.http_method.should == 'post'
36
+ end
37
+
38
+ end
39
+
40
+ describe "url" do
41
+
42
+ it "constructs a base URL" do
43
+ @request.url.should == "http://beta.wordnik.com/v4/words.json/fancy"
44
+ end
45
+
46
+ it "constructs a query string" do
47
+ @request.query_string.should == "?bar=2&foo=1"
48
+ end
49
+
50
+ it "constructs a full url" do
51
+ @request.url_with_query_string.should == "http://beta.wordnik.com/v4/words.json/fancy?bar=2&foo=1"
52
+ end
53
+
54
+ it "accounts for excessive slashes" do
55
+ @request = Request.new(:get, "andBurn", @default_params.merge({
56
+ :host => "slash.com/"
57
+ }))
58
+ @request.url.should == "http://slash.com/andBurn.json"
59
+ end
60
+
61
+ end
62
+
63
+ describe "path" do
64
+
65
+ it "accounts for a total absence of format in the path string" do
66
+ @request = Request.new(:get, "/word/{word}/entries", @default_params.merge({
67
+ :format => "xml",
68
+ :params => {
69
+ :word => "cat"
70
+ }
71
+ }))
72
+ @request.url.should == "http://beta.wordnik.com/v4/word.xml/cat/entries"
73
+ end
74
+
75
+ it "does string substitution on path params" do
76
+ @request = Request.new(:get, "/word.{format}/{word}/entries", @default_params.merge({
77
+ :format => "xml",
78
+ :params => {
79
+ :word => "cat"
80
+ }
81
+ }))
82
+ @request.url.should == "http://beta.wordnik.com/v4/word.xml/cat/entries"
83
+ end
84
+
85
+ it "leaves path-bound params out of the query string" do
86
+ @request = Request.new(:get, "/word.{format}/{word}/entries", @default_params.merge({
87
+ :params => {
88
+ :word => "cat",
89
+ :limit => 20
90
+ }
91
+ }))
92
+ @request.query_string.should == "?limit=20"
93
+ end
94
+
95
+ it "returns a question-mark free (blank) query string if no query params are present" do
96
+ @request = Request.new(:get, "/word.{format}/{word}/entries", @default_params.merge({
97
+ :params => {
98
+ :word => "cat",
99
+ }
100
+ }))
101
+ @request.query_string.should == ""
102
+ end
103
+
104
+ it "removes blank params" do
105
+ @request = Request.new(:get, "words/fancy", @default_params.merge({
106
+ :params => {
107
+ :word => "dog",
108
+ :limit => "",
109
+ :foo => "criminy"
110
+ }
111
+ }))
112
+ @request.query_string.should == "?foo=criminy&word=dog"
113
+ end
114
+
115
+ it "obfuscates the API key when needed" do
116
+ @request = Request.new(:get, "words/fancy", @default_params.merge({
117
+ :params => {
118
+ :word => "dog",
119
+ :api_key => "123456"
120
+ }
121
+ }))
122
+ @request.query_string_params.should == {:word => "dog", :api_key => "123456"}
123
+ @request.query_string_params(true).should == {:word => "dog", :api_key => "YOUR_API_KEY"}
124
+
125
+ @request.query_string.should == "?api_key=123456&word=dog"
126
+ @request.query_string(:obfuscated => true).should == "?api_key=YOUR_API_KEY&word=dog"
127
+
128
+ @request.url_with_query_string.should =~ /123456/
129
+ @request.url_with_query_string(:obfuscated => true).should =~ /YOUR\_API\_KEY/
130
+ end
131
+
132
+ it "URI encodes the path" do
133
+ @request = Request.new(:get, "word.{format}/{word}/definitions", @default_params.merge({
134
+ :params => {
135
+ :word => "bill gates"
136
+ }
137
+ }))
138
+ @request.url.should =~ /word.json\/bill\%20gates\/definitions/
139
+ end
140
+
141
+ it "converts numeric params to strings" do
142
+ @request = Request.new(@default_http_method, @default_path, @default_params.merge({
143
+ :params => {
144
+ :limit => 100
145
+ }
146
+ }))
147
+
148
+ @request.interpreted_path.should_not be_nil
149
+ @request.query_string.should =~ /\?limit=100/
150
+ @request.url_with_query_string.should =~ /\?limit=100/
151
+ end
152
+
153
+ end
154
+
155
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resource do
4
+
5
+ before(:each) do
6
+ VCR.use_cassette('words', :record => :new_episodes) do
7
+ @response = Typhoeus::Request.get("http://api.wordnik.com/v4/word.json")
8
+ end
9
+
10
+ @default_params = {
11
+ :name => "word",
12
+ :raw_data => JSON.parse(@response.body)
13
+ }
14
+
15
+ @resource = Resource.new(@default_params)
16
+ end
17
+
18
+ describe "initialization" do
19
+
20
+ it "successfully initializes" do
21
+ @resource.name.should == "word"
22
+ end
23
+
24
+ it "sets endpoints" do
25
+ @resource.endpoints.size.should == 10
26
+ @resource.endpoints.first.class.to_s.should == "Endpoint"
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Response do
4
+
5
+ before(:each) do
6
+
7
+ VCR.use_cassette('default_response_request', :record => :new_episodes) do
8
+ @raw = Typhoeus::Request.get("http://api.wordnik.com/v4/word.json")
9
+ end
10
+
11
+ @response = Response.new(@raw)
12
+ end
13
+
14
+ describe "initialization" do
15
+ it "sets body" do
16
+ @response.body.class.should == Hash
17
+ @response.body.has_key?('endPoints').should == true
18
+ end
19
+
20
+ it "sets code" do
21
+ @response.code.should == 200
22
+ end
23
+
24
+ it "converts header string into a hash" do
25
+ @response.headers.class.should == Hash
26
+ @response.headers['Wordnik-Api-Version'].to_s.should =~ /4\.0/
27
+ end
28
+
29
+ end
30
+
31
+ describe "format" do
32
+
33
+ it "recognizes json" do
34
+ @response.format.should == :json
35
+ @response.json?.should == true
36
+ end
37
+
38
+ it "recognizes xml" do
39
+ VCR.use_cassette('xml_response_request', :record => :new_episodes) do
40
+ @raw = Typhoeus::Request.get("http://api.wordnik.com/v4/word.xml/help")
41
+ end
42
+ @response = Response.new(@raw)
43
+ @response.format.should == :xml
44
+ @response.xml?.should == true
45
+ end
46
+
47
+ end
48
+
49
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'wordnik'
4
+ require 'vcr'
5
+ require 'typhoeus'
6
+ require 'json'
7
+
8
+ RSpec.configure do |config|
9
+ # some (optional) config here
10
+ end
11
+
12
+ VCR.config do |config|
13
+ config.cassette_library_dir = 'spec/vcr'
14
+ config.stub_with :webmock # or :fakeweb
15
+ end
16
+
17
+ Wordnik.configure do |config|
18
+ config.api_key = "12345"
19
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Wordnik do
4
+
5
+ context "in the near future" do
6
+
7
+ it "does cool stuff"
8
+
9
+ end
10
+
11
+ end
data/wordnik.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "wordnik/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "wordnik"
7
+ s.version = Wordnik::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Zeke Sikelianos", "John McGrath"]
10
+ s.email = ["zeke@wordnik.com", "john@wordnik.com"]
11
+ s.homepage = "http://developer.wordnik.com"
12
+ s.summary = %q{A ruby wrapper for the Wordnik API}
13
+ s.description = %q{This gem provides a simple interface to the entire Wordnik API. Its methods are defined by the documentation that comes from the API itself, so it's guaranteed to be up to date.}
14
+
15
+ s.rubyforge_project = "wordnik"
16
+
17
+ s.add_dependency 'typhoeus', '0.2.1'
18
+ s.add_dependency 'htmlentities', '4.2.4'
19
+ s.add_dependency 'addressable', '2.2.4'
20
+ s.add_dependency 'nokogiri', '1.4.4'
21
+ s.add_dependency 'activemodel', '3.0.3'
22
+ s.add_dependency 'json', '1.4.6'
23
+
24
+ s.add_development_dependency 'rspec', '2.4.0'
25
+ s.add_development_dependency 'vcr', '1.5.1'
26
+ s.add_development_dependency 'webmock', '1.6.2'
27
+
28
+ s.files = `git ls-files`.split("\n")
29
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
31
+ s.require_paths = ["lib"]
32
+ end
metadata ADDED
@@ -0,0 +1,232 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wordnik
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Zeke Sikelianos
13
+ - John McGrath
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-16 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: typhoeus
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ - 2
32
+ - 1
33
+ version: 0.2.1
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: htmlentities
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - "="
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 4
46
+ - 2
47
+ - 4
48
+ version: 4.2.4
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: addressable
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - "="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 2
61
+ - 2
62
+ - 4
63
+ version: 2.2.4
64
+ type: :runtime
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: nokogiri
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - "="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 1
76
+ - 4
77
+ - 4
78
+ version: 1.4.4
79
+ type: :runtime
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ name: activemodel
83
+ prerelease: false
84
+ requirement: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - "="
88
+ - !ruby/object:Gem::Version
89
+ segments:
90
+ - 3
91
+ - 0
92
+ - 3
93
+ version: 3.0.3
94
+ type: :runtime
95
+ version_requirements: *id005
96
+ - !ruby/object:Gem::Dependency
97
+ name: json
98
+ prerelease: false
99
+ requirement: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - "="
103
+ - !ruby/object:Gem::Version
104
+ segments:
105
+ - 1
106
+ - 4
107
+ - 6
108
+ version: 1.4.6
109
+ type: :runtime
110
+ version_requirements: *id006
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ prerelease: false
114
+ requirement: &id007 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - "="
118
+ - !ruby/object:Gem::Version
119
+ segments:
120
+ - 2
121
+ - 4
122
+ - 0
123
+ version: 2.4.0
124
+ type: :development
125
+ version_requirements: *id007
126
+ - !ruby/object:Gem::Dependency
127
+ name: vcr
128
+ prerelease: false
129
+ requirement: &id008 !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - "="
133
+ - !ruby/object:Gem::Version
134
+ segments:
135
+ - 1
136
+ - 5
137
+ - 1
138
+ version: 1.5.1
139
+ type: :development
140
+ version_requirements: *id008
141
+ - !ruby/object:Gem::Dependency
142
+ name: webmock
143
+ prerelease: false
144
+ requirement: &id009 !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - "="
148
+ - !ruby/object:Gem::Version
149
+ segments:
150
+ - 1
151
+ - 6
152
+ - 2
153
+ version: 1.6.2
154
+ type: :development
155
+ version_requirements: *id009
156
+ description: This gem provides a simple interface to the entire Wordnik API. Its methods are defined by the documentation that comes from the API itself, so it's guaranteed to be up to date.
157
+ email:
158
+ - zeke@wordnik.com
159
+ - john@wordnik.com
160
+ executables: []
161
+
162
+ extensions: []
163
+
164
+ extra_rdoc_files: []
165
+
166
+ files:
167
+ - .gitignore
168
+ - Gemfile
169
+ - Gemfile.lock
170
+ - README.md
171
+ - Rakefile
172
+ - lib/wordnik.rb
173
+ - lib/wordnik/configuration.rb
174
+ - lib/wordnik/endpoint.rb
175
+ - lib/wordnik/operation.rb
176
+ - lib/wordnik/operation_parameter.rb
177
+ - lib/wordnik/request.rb
178
+ - lib/wordnik/resource.rb
179
+ - lib/wordnik/response.rb
180
+ - lib/wordnik/version.rb
181
+ - spec/endpoint_spec.rb
182
+ - spec/operation_parameter_spec.rb
183
+ - spec/operation_spec.rb
184
+ - spec/request_spec.rb
185
+ - spec/resource_spec.rb
186
+ - spec/response_spec.rb
187
+ - spec/spec.opts
188
+ - spec/spec_helper.rb
189
+ - spec/wordnik_spec.rb
190
+ - wordnik.gemspec
191
+ has_rdoc: true
192
+ homepage: http://developer.wordnik.com
193
+ licenses: []
194
+
195
+ post_install_message:
196
+ rdoc_options: []
197
+
198
+ require_paths:
199
+ - lib
200
+ required_ruby_version: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ segments:
206
+ - 0
207
+ version: "0"
208
+ required_rubygems_version: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ segments:
214
+ - 0
215
+ version: "0"
216
+ requirements: []
217
+
218
+ rubyforge_project: wordnik
219
+ rubygems_version: 1.3.7
220
+ signing_key:
221
+ specification_version: 3
222
+ summary: A ruby wrapper for the Wordnik API
223
+ test_files:
224
+ - spec/endpoint_spec.rb
225
+ - spec/operation_parameter_spec.rb
226
+ - spec/operation_spec.rb
227
+ - spec/request_spec.rb
228
+ - spec/resource_spec.rb
229
+ - spec/response_spec.rb
230
+ - spec/spec.opts
231
+ - spec/spec_helper.rb
232
+ - spec/wordnik_spec.rb