Skip to content

Commit

Permalink
Add support for search route
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewshafer committed May 9, 2013
1 parent 79f5c20 commit dff3759
Show file tree
Hide file tree
Showing 6 changed files with 332 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Add params method to beer. Allows passing additional parameters in an additional way.
* Add styles method & class. Allows querying of the /styles route
* Add style method & class. Allows querying of the /style/:id route
# Add search method & class. Allows querying of the /search route

## v0.0.1
* Support for querying a beer
Expand Down
88 changes: 88 additions & 0 deletions lib/tankard/api/search.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require 'hashie'
require 'tankard/api/utils/page_finders'

module Tankard
module Api
class Search
include ::Enumerable
include Tankard::Api::Utils::PageFinders

def initialize(request, options={})
@request = request
@options = Hashie::Mash.new(options)
end

def each(&block)
raise_if_required_options_not_set

if options_have_page_set
find_on_single_page(uri_from_options_endpoint, @request, @options, block)
else
find_on_all_pages(uri_from_options_endpoint, @request, @options, block)
end
end

def query(search_query)
@options.q = search_query
self
end

def page(number)
@options.p = number
self
end

def params(options={})
options.each_pair do |key,value|
@options[key] = value
end
self
end

def type(search_type)
@options.type = search_type
self
end

def upc(upc_code)
@options.code = upc_code
@options.endpoint = "upc"
self
end

def geo_point(latitude, longitude)
@options.lat = latitude
@options.lng = longitude
@options.endpoint = "geo/point"
self
end

private

def options_have_page_set
@options.has_key?(:p)
end

def uri_from_options_endpoint
endpoint = "search"

if @options.endpoint?
endpoint += "/#{@options.delete(:endpoint)}"
end

endpoint
end

def raise_if_required_options_not_set
case @options.endpoint
when nil
raise Tankard::Error::NoSearchQuery unless @options.q?
when "upc"
raise Tankard::Error::MissingParameter, "missing parameter: code" unless @options.code?
when "geo/point"
raise Tankard::Error::MissingParameter, "missing Parameters: lat, lng" unless @options.lat? && @options.lng?
end
end
end
end
end
5 changes: 5 additions & 0 deletions lib/tankard/client.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'tankard/request'
require 'tankard/api/beer'
require 'tankard/api/beers'
require 'tankard/api/search'
require 'tankard/api/styles'
require 'tankard/api/style'

Expand All @@ -23,6 +24,10 @@ def beers(options={})
Tankard::Api::Beers.new(@tankard_request, options)
end

def search(options={})
Tankard::Api::Search.new(@tankard_request, options)
end

def styles
Tankard::Api::Styles.new(@tankard_request)
end
Expand Down
2 changes: 2 additions & 0 deletions lib/tankard/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module Error
ConfigurationError = Class.new(::StandardError)
NoBeerId = Class.new(::StandardError)
NoStyleId = Class.new(::StandardError)
NoSearchQuery = Class.new(::StandardError)
MissingParameter = Class.new(::StandardError)
HttpError = Class.new(::StandardError)
LoadError = Class.new(::StandardError)
InvalidResponse = Class.new(::StandardError)
Expand Down
212 changes: 212 additions & 0 deletions spec/tankard/api/search_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
require 'spec_helper'

describe Tankard::Api::Search do

let(:search) { Tankard::Api::Search.new(@request) }

before do
@request = mock("request")
end

describe "#query" do

it "sets options[:q] with the query the user wants to run" do
search.query("test")
search_options = search.instance_variable_get(:"@options")
expect(search_options[:q]).to eql("test")
end

it "returns itself" do
expect(search.object_id).to eql(search.query("test").object_id)
end

end

describe "#params" do

it "sets parameters" do
search.params(withSocialAccounts: "y", withGuilds: "n")
search_options = search.instance_variable_get(:"@options")
expect(search_options[:withSocialAccounts]).to eql("y")
expect(search_options[:withGuilds]).to eql("n")
end

it "merges params when called multiple times" do
search.params(test: "n")
search.params(test: "y")
search_options = search.instance_variable_get(:"@options")
expect(search_options[:test]).to eql("y")
end

it "returns itself" do
expect(search.object_id).to eql(search.params.object_id)
end
end

describe "#type" do

it "sets options[:type] with the type to search for" do
search.type("beer")
search_options = search.instance_variable_get(:"@options")
expect(search_options[:type]).to eql("beer")
end

it "returns itself" do
expect(search.object_id).to eql (search.type("test").object_id)
end
end

describe "#page" do

it "sets options[:p] with the page number to load" do
search.page(1)
search_options = search.instance_variable_get(:"@options")
expect(search_options[:p]).to eql(1)
end

it "returns itself" do
expect(search.object_id).to eql(search.page(1).object_id)
end
end

describe "#upc" do

before do
search.upc("123")
@search_options = search.instance_variable_get(:"@options")
end

it "sets options[:endpoint] with the search endpoint to use" do
expect(@search_options[:endpoint]).to eql("upc")
end

it "sets options[:code] with the upc code" do
expect(@search_options[:code]).to eql("123")
end

it "returns itself" do
expect(search.object_id).to eql(search.upc("123").object_id)
end
end

describe "#geo_point" do

before do
search.geo_point(1.23, 4.56)
@search_options = search.instance_variable_get(:"@options")
end

it "sets options[:endpoint] with the correct search endpoint to use" do
expect(@search_options[:endpoint]).to eql("geo/point")
end

it "sets options[:lat] with the latitude" do
expect(@search_options[:lat]).to eql(1.23)
end

it "sets options[:lng] with the longitude" do
expect(@search_options[:lng]).to eql(4.56)
end

it "returns itself" do
expect(search.object_id).to eql(search.geo_point(1.3, 4.5).object_id)
end
end

describe "when making a request" do

context "and a page is set" do

it "only queries a single page" do
search.should_receive(:find_on_single_page)
search.query("test").page(1).each { |x| x }
end
end

context "and a page is not set" do

it "queries multiple pages" do
search.should_receive(:find_on_all_pages)
search.query("test").each { |x| x }
end
end

context "and the search query is not set" do

it "raises Tankard::Error::NoSearchQuery" do
expect { search.each { |s| p s } }.to raise_error(Tankard::Error::NoSearchQuery)
end
end

context "and the search query is set" do

before do
@request.stub(:get).with("search", Hashie::Mash.new(p: 1, q: "test")).and_return("data" => ["search_result"])
end

it "uses the query in the request parameters" do
expect(search.query("test").collect { |x| x }).to eql(["search_result"])
end
end

context "the endpoint is set" do

before do
@request.stub(:get).with("search/upc", Hashie::Mash.new(code: "123", p: 1)).and_return({ "data" => ["search_result"] })
end

it "adds the endpoint to the request" do
expect(search.upc("123").collect { |x| x }).to eql(["search_result"])
end
end

context "the upc endpoint is set without the code parameter" do

it "raises Tankard::Error::MissingParameter" do
expect { search.params(endpoint: "upc").collect { |x| x } }. to raise_error(Tankard::Error::MissingParameter)
end
end

context "the geo/point endpoint isset without lat or lng parameters" do

it "raises Tankard::Error::MissingParameter when lat is set but lng isnt" do
expect { search.params(endpoint: "geo/point", lat: 123).collect { |x| x } }.to raise_error(Tankard::Error::MissingParameter)
end

it "raises Tankard::Error::MissingParameter when lng is set but lat isnt" do
expect { search.params(endpoint: "geo/point", lng: 2).collect { |x| x } }.to raise_error(Tankard::Error::MissingParameter)
end

it "raises Tankard::Error::MissingParameter when lat and lng are not set" do
expect { search.params(endpoint: "geo/point").collect { |x| x } }.to raise_error(Tankard::Error::MissingParameter)
end
end

context "additional options are set" do

before do
@search_with_options = Tankard::Api::Search.new(@request, test: "123", p: 1, q: "search")
@request.stub(:get).with("search", Hashie::Mash.new(test: "123", p: 1, q: "search")).and_return({ "data" => ["searched"] })
end

it "passes them to the request" do
expect(@search_with_options.collect { |x| x }).to eql(["searched"])
end
end

context "and no data is returned on a single page request" do

before do
@request.stub(:get).with("search", Hashie::Mash.new(q: "test", p: 1)).and_return({})
end

it "raises Tankard::Error::InvalidResponse" do
expect { search.query("test").page(1).collect { |x| x } }.to raise_error(Tankard::Error::InvalidResponse)
end
end

context "and no data is returned on a multi page request" do

end
end
end
24 changes: 24 additions & 0 deletions spec/tankard/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,30 @@
end
end

describe "#search" do

context "when called" do

it "does not reuse an existing search object" do
search = client.search
expect(search.object_id).not_to eql(client.search.object_id)
end
end

context "when passed a hash of options" do

before do
@request = mock("request")
Tankard::Request.stub!(:new).and_return(@request)
end

it "passes the options to the search object" do
Tankard::Api::Search.should_receive(:new).with(@request, { test: 123 })
client.search({ test: 123 })
end
end
end

describe "#styles" do

context "when called" do
Expand Down

0 comments on commit dff3759

Please sign in to comment.