wordnik 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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