├── .rspec.dist ├── lib ├── dinosaurus │ ├── version.rb │ ├── railties.rb │ ├── configuration.rb │ ├── logging.rb │ ├── results.rb │ └── thesaurus.rb └── dinosaurus.rb ├── Gemfile ├── Rakefile ├── .gitignore ├── spec ├── spec_helper.rb ├── dinosaurus │ ├── results_spec.rb │ ├── dinosaurus_spec.rb │ └── thesaurus_spec.rb └── fixtures │ └── vcr_cassettes │ ├── nonsense.yml │ ├── meal_people.yml │ └── word.yml ├── dinosaurus.gemspec ├── LICENSE └── README.md /.rspec.dist: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /lib/dinosaurus/version.rb: -------------------------------------------------------------------------------- 1 | module Dinosaurus 2 | VERSION = "0.0.12" 3 | end 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in dinosaurus.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | require "bundler/gem_tasks" 3 | 4 | require 'rspec/core/rake_task' 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | task default: :spec 9 | -------------------------------------------------------------------------------- /lib/dinosaurus/railties.rb: -------------------------------------------------------------------------------- 1 | module Dinosaurus 2 | class Railties < ::Rails::Railtie 3 | initializer 'Rails logger' do 4 | Dinosaurus::Logging.logger = Rails.logger 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | .rspec 19 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Require application. 2 | require "dinosaurus" 3 | 4 | # Require testing dependencies. 5 | require "vcr" 6 | 7 | # An API Key must b supplied in order to regenerate VCR casettes. 8 | # THis is a testing account API key. 9 | API_KEY = 'c5aedd41d31e32f3597100dd5b0d0163' 10 | 11 | VCR.configure do |c| 12 | c.cassette_library_dir = 'spec/fixtures/vcr_cassettes' 13 | c.hook_into :webmock # or :fakeweb 14 | c.ignore_hosts '127.0.0.1', 'localhost' 15 | 16 | if API_KEY 17 | c.filter_sensitive_data('') { API_KEY } 18 | end 19 | end 20 | 21 | Dinosaurus.configure do |c| 22 | c.api_key = API_KEY 23 | end 24 | -------------------------------------------------------------------------------- /lib/dinosaurus/configuration.rb: -------------------------------------------------------------------------------- 1 | # Enable setting and getting of configuration options. 2 | # 3 | # Example: 4 | # 5 | # This can now be used under config/initializers/dinosaurus.rb 6 | # Dinosaurus.configure do |config| 7 | # config.api_key = 'dfskljkf' 8 | # end 9 | 10 | module Dinosaurus 11 | class Configuration 12 | DEFAULT_LOG_LEVEL = 'info' 13 | 14 | attr_accessor :api_key, :log_level 15 | 16 | def initialize 17 | self.log_level = DEFAULT_LOG_LEVEL 18 | end 19 | end 20 | 21 | def self.configuration 22 | @configuration ||= Configuration.new 23 | end 24 | 25 | def self.configure 26 | yield configuration 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/dinosaurus/logging.rb: -------------------------------------------------------------------------------- 1 | require "logger" 2 | 3 | module Logging 4 | def logger 5 | Logging.logger 6 | end 7 | 8 | def self.logger 9 | unless @logger 10 | @logger = Logger.new(STDOUT) 11 | @logger.level = Logging.infer_level 12 | end 13 | @logger 14 | end 15 | 16 | # infer a suitable Log level from the ENVIRONMENT variable 17 | # Can pass in an environment value for testing purposes 18 | def self.infer_level(level = nil) 19 | level = level || Dinosaurus.configuration.log_level 20 | case level 21 | when 'debug' then Logger::DEBUG 22 | when 'warn' then Logger::WARN 23 | else Logger::INFO # default 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/dinosaurus/results.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/hash/indifferent_access" 2 | 3 | module Dinosaurus 4 | class Results < HashWithIndifferentAccess 5 | 6 | def initialize(data = {}) 7 | super(data) 8 | end 9 | 10 | # Define some convenience methods. 11 | { 'synonyms' => :syn, 12 | 'antonyms' => :ant, 13 | 'similar_terms' => :sim, 14 | 'related_terms' => :rel 15 | }.each do |name, key| 16 | define_method name do 17 | grouped(key) 18 | end 19 | end 20 | 21 | private 22 | 23 | def grouped(key) 24 | group = [] 25 | self.each do |pos, type| 26 | group += type[key] if type[key] 27 | end 28 | group 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/dinosaurus/results_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Dinosaurus::Results do 4 | let(:noun) do 5 | { 'syn' => %w[syn1 syn2 syn3], 6 | 'sim' => %w[sim1 sim2], 7 | 'ant' => %w[ant1] } 8 | end 9 | 10 | let(:res) do 11 | { 12 | 'noun' => noun, 13 | 'verb' => { 14 | 'rel' => %w[rel1 rel2 rel3], 15 | 'syn' => %w[vsyn1] 16 | } 17 | } 18 | end 19 | 20 | subject { described_class.new(res) } 21 | 22 | it "makes synonyms available" do 23 | expect(subject.synonyms).to eq(%w[syn1 syn2 syn3 vsyn1]) 24 | end 25 | 26 | it "makes all antonyms available" do 27 | expect(subject.antonyms).to eq(%w[ant1]) 28 | end 29 | 30 | it "makes similar terms available" do 31 | expect(subject.similar_terms).to eq(%w[sim1 sim2]) 32 | end 33 | 34 | it "makes related terms available" do 35 | expect(subject.related_terms).to eq(%w[rel1 rel2 rel3]) 36 | end 37 | 38 | it "makes nouns available" do 39 | expect(subject[:noun]).to eq(noun) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /dinosaurus.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path('../lib/dinosaurus/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["David Tuite"] 6 | gem.email = ["dtuite@gmail.com"] 7 | gem.description = %q{Ruby wrapper for the Big Huge Thesaurus APIs.} 8 | gem.summary = %q{Lookup synonyms, antonyms etc. using the Big Huge Thesaurus API.} 9 | gem.homepage = "http://words.bighugelabs.com" 10 | 11 | gem.files = `git ls-files`.split($\) 12 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 13 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 14 | gem.name = "dinosaurus" 15 | gem.require_paths = ["lib"] 16 | gem.version = Dinosaurus::VERSION 17 | 18 | gem.add_development_dependency "rspec" 19 | gem.add_development_dependency "vcr" 20 | gem.add_development_dependency "webmock" 21 | 22 | gem.add_dependency "httparty" 23 | gem.add_dependency "activesupport" 24 | gem.add_dependency "rake" 25 | end 26 | -------------------------------------------------------------------------------- /lib/dinosaurus/thesaurus.rb: -------------------------------------------------------------------------------- 1 | require "httparty" 2 | require "json" 3 | require "uri" 4 | require "active_support/core_ext/object/blank" 5 | 6 | module Dinosaurus 7 | class MissingApiKeyError < StandardError; end 8 | class RemoteServiceError < StandardError; end 9 | 10 | class Thesaurus 11 | include HTTParty 12 | base_uri "words.bighugelabs.com" 13 | format :json 14 | 15 | def self.lookup(word) 16 | return Dinosaurus::Results.new if word.blank? 17 | res = get(url_for(word)) 18 | 19 | if res.code == 200 20 | Dinosaurus::Results.new(JSON.parse(res.body)) 21 | # Word does not exist. 22 | elsif res.code == 404 23 | Dinosaurus::Results.new 24 | else 25 | Logging.logger.warn("DINOSAURUS_WARNING: #{res.code}. WORD: #{word}.") 26 | end 27 | end 28 | 29 | private 30 | 31 | def self.url_for(word) 32 | key = Dinosaurus.configuration.api_key 33 | raise MissingApiKeyError unless key 34 | URI.encode("/api/2/" + key + '/' + word + '/json') 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 David Tuite 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /spec/dinosaurus/dinosaurus_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Dinosaurus do 4 | let(:res) { Dinosaurus::Results.new } 5 | before { allow(Dinosaurus).to receive(:lookup).and_return(res) } 6 | 7 | describe "#synonyms_of" do 8 | it "should return synonyms" do 9 | allow(res).to receive(:synonyms) 10 | Dinosaurus.synonyms_of('normal') 11 | expect(res).to have_received(:synonyms) 12 | end 13 | end 14 | 15 | describe "#antonyms_of" do 16 | it "should return antonyms" do 17 | allow(res).to receive(:antonyms) 18 | Dinosaurus.antonyms_of('normal') 19 | expect(res).to have_received(:antonyms) 20 | end 21 | end 22 | 23 | describe "#related_to" do 24 | it "should return related terms" do 25 | allow(res).to receive(:related_terms) 26 | Dinosaurus.related_to('normal') 27 | expect(res).to have_received(:related_terms) 28 | end 29 | end 30 | 31 | describe "#similar_to" do 32 | it "should return similar terms" do 33 | allow(res).to receive(:similar_terms) 34 | Dinosaurus.similar_to('normal') 35 | expect(res).to have_received(:similar_terms) 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/dinosaurus/thesaurus_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | describe Dinosaurus::Thesaurus do 4 | it "should return results" do 5 | VCR.use_cassette('word') do 6 | expect(described_class.lookup('word')).to be_instance_of(Dinosaurus::Results) 7 | end 8 | end 9 | 10 | it "should log errors" do 11 | allow(described_class).to receive(:get).and_return(double(code: 500)) 12 | allow(Logging.logger).to receive(:warn) 13 | VCR.use_cassette('word') { described_class.lookup('word') } 14 | expect(Logging.logger).to have_received(:warn) 15 | end 16 | 17 | it "should return {} for nonsense words" do 18 | VCR.use_cassette('nonsense') do 19 | expect(described_class.lookup('hsdfkjhsf')).to eq({}) 20 | end 21 | end 22 | 23 | it "should handle two words" do 24 | VCR.use_cassette('meal_people') do 25 | expect(described_class.lookup('meal people')).to eq({}) 26 | end 27 | end 28 | 29 | it "should raise up if missing api key" do 30 | allow(Dinosaurus.configuration).to receive(:api_key) 31 | expect do 32 | described_class.lookup('word') 33 | end.to raise_error(Dinosaurus::MissingApiKeyError) 34 | end 35 | 36 | it "should raise if the server 500" 37 | end 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/nonsense.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: http://words.bighugelabs.com/api/2//hsdfkjhsf/json 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | response: 17 | status: 18 | code: 404 19 | message: Not Found 20 | headers: 21 | Server: 22 | - nginx/1.4.6 (Ubuntu) 23 | Date: 24 | - Thu, 28 May 2015 10:27:27 GMT 25 | Content-Type: 26 | - text/html 27 | Content-Length: 28 | - '0' 29 | Connection: 30 | - keep-alive 31 | X-Powered-By: 32 | - PHP/5.5.9-1ubuntu4.9 33 | Set-Cookie: 34 | - PHPSESSID=1njnsimbjub81i5llb36ch0co2; path=/; domain=words.bighugelabs.com 35 | Expires: 36 | - Thu, 19 Nov 1981 08:52:00 GMT 37 | Cache-Control: 38 | - no-store, no-cache, must-revalidate, post-check=0, pre-check=0 39 | Pragma: 40 | - no-cache 41 | Access-Control-Allow-Origin: 42 | - "*" 43 | body: 44 | encoding: UTF-8 45 | string: '' 46 | http_version: 47 | recorded_at: Thu, 28 May 2015 10:27:27 GMT 48 | recorded_with: VCR 2.9.3 49 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/meal_people.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: http://words.bighugelabs.com/api/2//meal%20people/json 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | response: 17 | status: 18 | code: 404 19 | message: Not Found 20 | headers: 21 | Server: 22 | - nginx/1.4.6 (Ubuntu) 23 | Date: 24 | - Thu, 28 May 2015 10:27:27 GMT 25 | Content-Type: 26 | - text/html 27 | Content-Length: 28 | - '0' 29 | Connection: 30 | - keep-alive 31 | X-Powered-By: 32 | - PHP/5.5.9-1ubuntu4.9 33 | Set-Cookie: 34 | - PHPSESSID=uj74tu3a6rqfova6b01sl0c5l7; path=/; domain=words.bighugelabs.com 35 | Expires: 36 | - Thu, 19 Nov 1981 08:52:00 GMT 37 | Cache-Control: 38 | - no-store, no-cache, must-revalidate, post-check=0, pre-check=0 39 | Pragma: 40 | - no-cache 41 | Access-Control-Allow-Origin: 42 | - "*" 43 | body: 44 | encoding: UTF-8 45 | string: '' 46 | http_version: 47 | recorded_at: Thu, 28 May 2015 10:27:27 GMT 48 | recorded_with: VCR 2.9.3 49 | -------------------------------------------------------------------------------- /lib/dinosaurus.rb: -------------------------------------------------------------------------------- 1 | require "dinosaurus/logging" 2 | require "dinosaurus/configuration" 3 | require "dinosaurus/results" 4 | require "dinosaurus/thesaurus" 5 | require "dinosaurus/version" 6 | 7 | module Dinosaurus 8 | # Lookup a word in the Big Huge Thesaurus. 9 | # 10 | # +word+ is expected to be a string. This method is 11 | # a no-op if the +word+ is blank as defined by ActiveSupport. 12 | # 13 | # Dinosaurus.lookup('people') 14 | # 15 | # Returns an instance of Dinosaurus::Results 16 | def self.lookup(word) 17 | Dinosaurus::Thesaurus.lookup(word) 18 | end 19 | 20 | # Convenience method to retrieve synonyms of a +word+. 21 | # 22 | # Dinosaurus.synonyms_of('people') 23 | # 24 | # Returns an array. 25 | def self.synonyms_of(word) 26 | lookup(word).synonyms 27 | end 28 | 29 | # Convenience method to retrieve antonyms of a +word+. 30 | # 31 | # Dinosaurus.antonyms_of('people') 32 | # 33 | # Returns an array. 34 | def self.antonyms_of(word) 35 | lookup(word).antonyms 36 | end 37 | 38 | # Convenience method to retrieve similar terms to the 39 | # given +word+. 40 | # 41 | # Dinosaurus.similar_to('people') 42 | # 43 | # Returns an array. 44 | def self.similar_to(word) 45 | lookup(word).similar_terms 46 | end 47 | 48 | # Convenience method to retrieve terms which are 49 | # related to the given +word+. 50 | # 51 | # Dinosaurus.related_to('people') 52 | # 53 | # Returns an array. 54 | def self.related_to(word) 55 | lookup(word).related_terms 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/word.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: http://words.bighugelabs.com/api/2//word/json 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Accept-Encoding: 11 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 12 | Accept: 13 | - "*/*" 14 | User-Agent: 15 | - Ruby 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | Server: 22 | - nginx/1.4.6 (Ubuntu) 23 | Date: 24 | - Thu, 28 May 2015 10:27:26 GMT 25 | Content-Type: 26 | - text/javascript 27 | Transfer-Encoding: 28 | - chunked 29 | Connection: 30 | - keep-alive 31 | Vary: 32 | - Accept-Encoding 33 | X-Powered-By: 34 | - PHP/5.5.9-1ubuntu4.9 35 | Set-Cookie: 36 | - PHPSESSID=9a03pfgor6otp9f5776bnqt4m4; path=/; domain=words.bighugelabs.com 37 | Expires: 38 | - Thu, 19 Nov 1981 08:52:00 GMT 39 | Cache-Control: 40 | - no-store, no-cache, must-revalidate, post-check=0, pre-check=0 41 | Pragma: 42 | - no-cache 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | body: 46 | encoding: ASCII-8BIT 47 | string: '{"noun":{"syn":["news","intelligence","tidings","discussion","give-and-take","parole","word 48 | of honor","Son","Word","Logos","password","watchword","countersign","Bible","Christian 49 | Bible","Book","Good Book","Holy Scripture","Holy Writ","Scripture","Word of 50 | God","arcanum","computer memory unit","hypostasis","hypostasis of Christ","info","information","language","language 51 | unit","linguistic unit","oral communication","order","positive identification","promise","religious 52 | text","religious writing","sacred text","sacred writing","secret","speech","speech 53 | communication","spoken communication","spoken language","statement","voice 54 | communication"]},"verb":{"syn":["give voice","formulate","phrase","articulate","evince","express","show"]}}' 55 | http_version: 56 | recorded_at: Thu, 28 May 2015 10:27:26 GMT 57 | recorded_with: VCR 2.9.3 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dinosaurus [![Build Status](https://secure.travis-ci.org/dtuite/dinosaurus.png?branch=master)](http://travis-ci.org/dtuite/dinosaurus) 2 | 3 | Ruby wrapper for the [Big Huge Labs Thesaurus](http://words.bighugelabs.com/) API. 4 | 5 | ## Installation 6 | 7 | Add this line to your application's Gemfile: 8 | 9 | gem 'dinosaurus' 10 | 11 | And then execute: 12 | 13 | $ bundle 14 | 15 | Or install it yourself as: 16 | 17 | $ gem install dinosaurus 18 | 19 | ## Usage 20 | 21 | ### Basic 22 | 23 | Add your api key using the `configure` method. If you're in the Rails 24 | environemnt then this can be done in an initializer file. 25 | 26 | Dinosaurus.configure do |config| 27 | config.api_key = 'djksfhjk' 28 | end 29 | 30 | Now, lookup words in the Thesaurus: 31 | 32 | require "dinosaurus" 33 | results = Dinosaurus.lookup('word') 34 | 35 | ### Results 36 | 37 | The 'results' object is a hash with some special accessors added. 38 | 39 | # You can use it like a normal hash: 40 | results['noun'] 41 | # => { 'syn' => [..., ..., ...], 'ant' => [..., ...] } 42 | 43 | # Or you can access it with symbols. 44 | results[:noun] 45 | # => { 'syn' => [..., ..., ...], 'ant' => [..., ...] } 46 | 47 | # Or you can take advantage of the special accesor methods. The 48 | # methods provided are 49 | # - synonyms 50 | # - antonyms 51 | # - related_terms 52 | # - similar_terms 53 | results.synonyms 54 | # => [..., ..., ...] 55 | 56 | ### Convenience Methods 57 | 58 | Certain convenience methods are provided on the top level namespace. 59 | Each method returns an array. 60 | 61 | Dinosaurus.synonyms_of('word') 62 | Dinosaurus.antonyms_of('word') 63 | Dinosaurus.related_to('word') 64 | Dinosaurus.similar_to('word') 65 | 66 | 67 | Slightly more information can be found on the [RubyDocs](http://rubydoc.info/github/dtuite/dinosaurus/master/frames). 68 | 69 | 70 | ## Contributing 71 | 72 | 1. Fork it 73 | 2. Create your feature branch (`git checkout -b my-new-feature`) 74 | 3. Commit your changes (`git commit -am 'Add some feature'`) 75 | 4. Push to the branch (`git push origin my-new-feature`) 76 | 5. Create new Pull Request 77 | --------------------------------------------------------------------------------