inquisitio 0.0.1 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e00221909913b20b1935e3893e2d28215e10c20b
4
- data.tar.gz: f09754c49440894e83dc6f510eb971f68df1ab25
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjA2YTc0ZDY2MWMwODRhODBlZGNjOWYzYzE3MzRkYjgwOGFiNjRkNg==
5
+ data.tar.gz: !binary |-
6
+ MDBmN2I1ZjMwMzEwZDk4MGQ4ZjZkZjEzNGY2ODZlYWEwNjBmYmY4NA==
5
7
  SHA512:
6
- metadata.gz: b30f62c09ea9a79aebc2ca49b03b6f1b23524a276843f4add66e690c2206889646ab336d2651cabbd7c2c4141d8f4d5d68be0b26b18b75ca67ab331d2f9e2012
7
- data.tar.gz: b06bfa625a9c9b7c1d47432771bb26fdc7302779b8c5e02434b34a3c49b1a8e3e515a111895d87983e9de738735bfd6eb468cf63c1fd3d510dd8700e6e79eee7
8
+ metadata.gz: !binary |-
9
+ MzJkN2U4OGE0ZmY4YWVlMjUxYmE3YjBmY2M0MmMzYTg0NmY4YjNlOGMyNTk3
10
+ YzUxNmVhZGM5ODk5Yzk4MGVhNWZjODBlM2I4NDk4OGZkNGUwM2Q2ZTUwZDNi
11
+ YWE4M2JlNjRhMzhhMTEzMWZmMDljYWYwZGU1ZDY1YTVmY2M0MzE=
12
+ data.tar.gz: !binary |-
13
+ NWVlYWQzYWJlNmM3MmI5NGM3ZGViNTNhODA3MmU4NTU0ZDlmYzUwMTYxMzE4
14
+ M2M4NGQ5ZDYxNWVjZTA5MzE5MDlhYmQ3ODVkYTM3M2EzZDNhN2Y2OWNkZjBh
15
+ Y2VmYjczNzhjMjg1YjBlMmVjMjhhMWU3OGU5ZDUwZTIzOTFjYzQ=
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ *.swp
1
2
  *.gem
2
3
  *.rbc
3
4
  .bundle
data/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ 0.0.11 / Unreleased
2
+
3
+ [FEATURE] Searcher now has default size read from configuration.
4
+ [FEATURE] Searcher now performs simple sanatization of search queries.
5
+
6
+ 0.0.9 / Unreleased
7
+
8
+ [FEATURE] Searcher now has id, records and results.
9
+ [FEATURE] Refactor SearchUrlBuilder out of Searcher.
10
+
11
+ 0.0.8 / 2013-10-23
12
+
13
+ [FEATURE] Extended searcher to handle arguments (for example, facet arguments).
14
+
15
+ 0.0.7 / 2013-10-23
16
+
17
+ [FEATURE] Extended searcher to handle boolean queries.
18
+
19
+ 0.0.6 / 2013-10-23
20
+
21
+ [FEATURE] Changed version of excon
22
+
23
+ 0.0.5 / 2013-10-22
24
+
25
+ [FEATURE] Initial indexer created.
26
+
27
+ 0.0.4 / 2013-10-22
28
+
29
+ [FEATURE] Return_fields is now optional in search call.
30
+
31
+ 0.0.3 / 2013-10-21
32
+
33
+ [FEATURE] Added ability to perform search using Searcher class.
34
+
35
+ 0.0.2 / 2013-10-21
36
+
37
+ [FEATURE] Added Document class representing AWS SDF document.
38
+
39
+ 0.0.1 / 2013-10-21
40
+
41
+ [FEATURE] Added configuration, logger and error classes.
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in inquisitio.gemspec
4
4
  gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/Rakefile CHANGED
@@ -1 +1,12 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+ require 'yard'
4
+
5
+ YARD::Rake::YardocTask.new do |t|
6
+ end
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.pattern = "test/**/*_test.rb"
10
+ end
11
+
12
+ task default: :test
data/bin/boolean_query ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "inquisitio"
7
+
8
+ # Perform a search containing a boolean query against AWS CloudSearch
9
+ #
10
+ # example usage:
11
+ #
12
+ # ruby ./bin/search <enddpoint> "Star Wars" "genre" "Animation" "title"
13
+
14
+ endpoint = ARGV[0]
15
+ query = ARGV[1]
16
+ filter_name = ARGV[2]
17
+ filter_value = ARGV[3]
18
+ return_fields = [ ARGV[4] ]
19
+
20
+ Inquisitio.config do |config|
21
+ config.search_endpoint = endpoint
22
+ end
23
+
24
+ puts Inquisitio.search(query, { filter_name.to_sym => filter_value.to_sym, :return_fields => return_fields} )
data/bin/facet_query ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "inquisitio"
7
+
8
+ # Perform a search containing a boolean query against AWS CloudSearch
9
+ #
10
+ # example usage:
11
+ #
12
+ # ruby ./bin/search <enddpoint> "Star Wars" "genre" "Animation" "title"
13
+
14
+ endpoint = ARGV[0]
15
+ query = ARGV[1]
16
+ filter_name = ARGV[2]
17
+ filter_value = ARGV[3]
18
+ return_fields = [ ARGV[4] ]
19
+
20
+ Inquisitio.config do |config|
21
+ config.search_endpoint = endpoint
22
+ end
23
+
24
+ puts Inquisitio.search(query,
25
+ { filter_name.to_sym => filter_value.to_sym,
26
+ :arguments => { :facet => 'genre',
27
+ 'facet-genre-constraints' => 'Animation',
28
+ 'facet-genre-top-n' => '5'
29
+ },
30
+ :return_fields => return_fields
31
+ } )
data/bin/index ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "inquisitio"
7
+
8
+ # Index a spdf file in AWS CloudSearch
9
+ #
10
+ # example usage:
11
+ #
12
+ # ruby ./bin/index <document_endpoint> "id" "version" "field_name" "field_value"
13
+
14
+ endpoint = ARGV[0]
15
+ id = ARGV[1]
16
+
17
+ version = Time.now.to_i
18
+
19
+ Inquisitio.config do |config|
20
+ config.document_endpoint = endpoint
21
+ end
22
+
23
+ fields = { :title => 'The Title',
24
+ :author => 'The Author' }
25
+ document = Inquisitio::Document.new("add",
26
+ id,
27
+ version,
28
+ fields)
29
+ Inquisitio.index(document)
data/bin/search ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "inquisitio"
7
+
8
+ # Perform a search against AWS CloudSearch
9
+ #
10
+ # example usage:
11
+ #
12
+ # ruby ./bin/search <enddpoint> "Star Wars" "title"
13
+
14
+ endpoint = ARGV[0]
15
+ query = ARGV[1]
16
+ return_fields = [ ARGV[2] ]
17
+
18
+ Inquisitio.config do |config|
19
+ config.search_endpoint = endpoint
20
+ end
21
+
22
+ if return_fields.nil?
23
+ puts Inquisitio.search(query)
24
+ else
25
+ puts Inquisitio.search(query, { "return_fields" => return_fields} )
26
+ end
data/inquisitio.gemspec CHANGED
@@ -18,6 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "excon", "~> 0.25.0"
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.3"
22
24
  spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "mocha"
26
+ spec.add_development_dependency "yard"
27
+ spec.add_development_dependency "minitest", "~> 5.0.8"
23
28
  end
@@ -0,0 +1,34 @@
1
+ module Inquisitio
2
+
3
+ class InquisitioConfigurationError < InquisitioError
4
+ end
5
+
6
+ class Configuration
7
+
8
+ SETTINGS = [
9
+ :search_endpoint,
10
+ :document_endpoint,
11
+ :default_search_size,
12
+ :logger
13
+ ]
14
+ attr_writer *SETTINGS
15
+
16
+ def initialize
17
+ self.logger = Inquisitio::Logger.new
18
+ end
19
+
20
+ SETTINGS.each do |setting|
21
+ define_method setting do
22
+ get_or_raise(setting)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def get_or_raise(setting)
29
+ instance_variable_get("@#{setting.to_s}") ||
30
+ raise(InquisitioConfigurationError.new("Configuration for #{setting} is not set"))
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,24 @@
1
+ require 'json'
2
+ module Inquisitio
3
+ class Document
4
+
5
+ attr_reader :type, :id, :version, :fields
6
+ def initialize(type, id, version, fields)
7
+ @type = type
8
+ @id = id
9
+ @version = version
10
+ @fields = fields
11
+ end
12
+
13
+ def to_SDF
14
+ <<-EOS
15
+ { "type": "#{type}",
16
+ "id": "#{id}",
17
+ "version": #{version},
18
+ "lang": "en",
19
+ "fields": #{fields.to_json}
20
+ }
21
+ EOS
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ require 'excon'
2
+
3
+ module Inquisitio
4
+ class Indexer
5
+
6
+ def self.index(documents)
7
+ new(documents).index
8
+ end
9
+
10
+ def initialize(documents)
11
+ raise InquisitioError.new("Document(s) is null") if documents.nil?
12
+ raise InquisitioError.new("Document(s) is empty") unless documents.any?
13
+
14
+ @documents = documents
15
+ end
16
+
17
+ def index
18
+ response = Excon.post(batch_index_url,
19
+ :body => body,
20
+ :headers => {"Content-Type" =>"application/json"})
21
+ raise InquisitioError.new("Index failed with status code: #{response.status} Message: #{response.body}") unless response.status == 200
22
+ response.body
23
+ end
24
+
25
+ private
26
+
27
+ def body
28
+ body = @documents.map(&:to_SDF).join(", ")
29
+ "[#{body}]"
30
+ end
31
+
32
+ def batch_index_url
33
+ "#{Inquisitio.config.document_endpoint}/2011-02-01/documents/batch"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module Inquisitio
2
+
3
+ # The exception from which all other exceptions in this library derive.
4
+ class InquisitioError < StandardError
5
+ end
6
+
7
+ end
@@ -0,0 +1,19 @@
1
+ module Inquisitio
2
+ class Logger
3
+
4
+ StdLevels = %W{debug info warn}
5
+ ErrorLevels = %W{error fatal}
6
+
7
+ StdLevels.each do |level|
8
+ define_method level do |*args|
9
+ $stdout.puts *args
10
+ end
11
+ end
12
+
13
+ ErrorLevels.each do |level|
14
+ define_method level do |*args|
15
+ $stderr.puts *args
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,59 @@
1
+ module Inquisitio
2
+ class SearchUrlBuilder
3
+
4
+ def self.build(*args)
5
+ new(*args).build
6
+ end
7
+
8
+ def initialize(options = {})
9
+ @query = options[:query]
10
+ @filters = options[:filters] || {}
11
+ @arguments = options[:arguments]
12
+ @return_fields = options[:return_fields]
13
+ add_default_size if @arguments.nil? || @arguments[:size].nil?
14
+ end
15
+
16
+ def build
17
+ components = [url_root]
18
+ components << (@filters.empty?? simple_query : boolean_query)
19
+ components << return_fields_query_string
20
+ components << arguments
21
+ components.join("")
22
+ end
23
+
24
+ private
25
+ def simple_query
26
+ "q=#{URI.encode(@query.gsub('\'',''))}"
27
+ end
28
+
29
+ def boolean_query
30
+ filters = @filters.map{|key,value| "#{key.to_s.gsub('\'','')}:'#{value.to_s.gsub('\'','')}'"}
31
+ queries = filters.join(" ")
32
+ queries = "'#{@query.gsub('\'','')}' #{queries}" if @query
33
+ "bq=#{URI.encode("(and #{queries})")}"
34
+ end
35
+
36
+ def return_fields_query_string
37
+ return "" if @return_fields.nil?
38
+ "&return-fields=#{URI::encode(@return_fields.join(',').gsub('\'',''))}"
39
+ end
40
+
41
+ def arguments
42
+ return "" if @arguments.nil?
43
+ @arguments.map{|key,value| "&#{key.to_s.gsub('\'','')}=#{value.to_s.gsub('\'','')}"}.join("")
44
+ end
45
+
46
+ def url_root
47
+ "#{Inquisitio.config.search_endpoint}/2011-02-01/search?"
48
+ end
49
+
50
+ def add_default_size
51
+ if @arguments.nil?
52
+ @arguments = {}
53
+ end
54
+ if @arguments[:size].nil?
55
+ @arguments = @arguments.merge(:size => Inquisitio.config.default_search_size)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,49 @@
1
+ require 'excon'
2
+
3
+ module Inquisitio
4
+ class Searcher
5
+
6
+ def self.search(*args)
7
+ searcher = new(*args)
8
+ searcher.search
9
+ searcher
10
+ end
11
+
12
+ attr_reader :results
13
+ def initialize(query, filters = {})
14
+ raise InquisitioError.new("Query is null") if query.nil?
15
+
16
+ if query.is_a?(String)
17
+ @query = query
18
+ @filters = filters
19
+ else
20
+ @filters = query
21
+ end
22
+
23
+ @return_fields = @filters.delete(:return_fields)
24
+ @arguments = @filters.delete(:arguments)
25
+ end
26
+
27
+ def search
28
+ response = Excon.get(search_url)
29
+ raise InquisitioError.new("Search failed with status code: #{response.status} Message #{response.body}") unless response.status == 200
30
+ body = response.body
31
+ @results = JSON.parse(body)["hits"]["hit"]
32
+ end
33
+
34
+ def ids
35
+ @ids ||= @results.map{|result|result['id']}
36
+ end
37
+
38
+ def records
39
+ @records ||= @results.map do |result|
40
+ {result['type'] => result['id']}
41
+ end
42
+ end
43
+
44
+ private
45
+ def search_url
46
+ @search_url ||= SearchUrlBuilder.build(query: @query, filters: @filters, arguments: @arguments, return_fields: @return_fields)
47
+ end
48
+ end
49
+ end
@@ -1,3 +1,3 @@
1
1
  module Inquisitio
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.11"
3
3
  end
data/lib/inquisitio.rb CHANGED
@@ -1,5 +1,50 @@
1
1
  require "inquisitio/version"
2
+ require "inquisitio/inquisitio_error"
3
+ require "inquisitio/logger"
4
+ require "inquisitio/configuration"
5
+ require "inquisitio/document"
6
+ require "inquisitio/search_url_builder"
7
+ require "inquisitio/searcher"
8
+ require "inquisitio/indexer"
2
9
 
3
10
  module Inquisitio
4
- # Your code goes here...
11
+
12
+ # Inquisitio configuration settings.
13
+ #
14
+ # Settings should be set in an initializer or using some
15
+ # other method that insures they are set before any
16
+ # Inquisitio code is used. They can be set as followed:
17
+ #
18
+ # Inquisitio.config.access_key = "my-access-key"
19
+ #
20
+ # The following settings are allowed:
21
+ #
22
+ # * <tt>:access_key</tt> - The AWS access key
23
+ # * <tt>:secret_key</tt> - The AWS secret key
24
+ # * <tt>:queue_region</tt> - The AWS region
25
+ # is included in.
26
+ # * <tt>:logger</tt> - A logger object that responds to puts.
27
+ def self.config
28
+ @config ||= Configuration.new
29
+ if block_given?
30
+ yield @config
31
+ else
32
+ @config
33
+ end
34
+ end
35
+
36
+ # Perform a search.
37
+ #
38
+ # @param [String] query The search query.
39
+ # @param [Hash] options. Optionaly specify return_fields. The fields to be returned in the search results.
40
+ def self.search(query, options = {})
41
+ Searcher.search(query, options)
42
+ end
43
+
44
+ # Index a batch of documents.
45
+ #
46
+ # @param [Array] documents. A list of Documents to index.
47
+ def self.index(documents)
48
+ Indexer.index([documents])
49
+ end
5
50
  end
@@ -0,0 +1,59 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Inquisitio
4
+ class ConfigurationTest < Minitest::Test
5
+
6
+ def setup
7
+ Inquisitio.instance_variable_set("@config", nil)
8
+ end
9
+
10
+ def test_obtaining_singletion
11
+ refute Inquisitio.config.nil?
12
+ end
13
+
14
+ def test_block_syntax
15
+ test_search_endpoint = "foobar-123-endpoint"
16
+ Inquisitio.config do |config|
17
+ config.search_endpoint = test_search_endpoint
18
+ end
19
+ assert_equal test_search_endpoint, Inquisitio.config.search_endpoint
20
+ end
21
+
22
+ def test_search_endpoint
23
+ search_endpoint = "test-search-endpoint"
24
+ Inquisitio.config.search_endpoint = search_endpoint
25
+ assert_equal search_endpoint, Inquisitio.config.search_endpoint
26
+ end
27
+
28
+ def test_missing_search_endpoint_throws_exception
29
+ assert_raises(InquisitioConfigurationError) do
30
+ Inquisitio.config.search_endpoint
31
+ end
32
+ end
33
+
34
+ def test_document_endpoint
35
+ document_endpoint = "test-document-endpoint"
36
+ Inquisitio.config.document_endpoint = document_endpoint
37
+ assert_equal document_endpoint, Inquisitio.config.document_endpoint
38
+ end
39
+
40
+ def test_missing_document_endpoint_throws_exception
41
+ assert_raises(InquisitioConfigurationError) do
42
+ Inquisitio.config.document_endpoint
43
+ end
44
+ end
45
+
46
+ def test_default_search_size
47
+ default_search_size = "test-default_search_size"
48
+ Inquisitio.config.default_search_size = default_search_size
49
+ assert_equal default_search_size, Inquisitio.config.default_search_size
50
+ end
51
+
52
+ def test_missing_default_search_size_throws_exception
53
+ assert_raises(InquisitioConfigurationError) do
54
+ Inquisitio.config.default_search_size
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+ require 'json'
3
+
4
+ module Inquisitio
5
+ class DocumentTest < Minitest::Test
6
+ def setup
7
+ @type = 'add'
8
+ @id = '12345'
9
+ @version = 1
10
+ @fields = { :title => 'The Title', :author => 'The Author' }
11
+ @document = Document.new(@type, @id, @version, @fields)
12
+
13
+ @expected_SDF =
14
+ <<-EOS
15
+ { "type": "add",
16
+ "id": "12345",
17
+ "version": 1,
18
+ "lang": "en",
19
+ "fields": {
20
+ "title": "The Title",
21
+ "author": "The Author"
22
+ }
23
+ }
24
+ EOS
25
+ end
26
+
27
+ def test_initialization_sets_type
28
+ assert_equal @type, @document.type
29
+ end
30
+
31
+ def test_initialization_sets_id
32
+ assert_equal @id, @document.id
33
+ end
34
+
35
+ def test_initialization_sets_version
36
+ assert_equal @version, @document.version
37
+ end
38
+
39
+ def test_initialization_sets_fields
40
+ assert_equal @fields, @document.fields
41
+ end
42
+
43
+ def test_create_valid_SDF_json
44
+ assert_equal JSON.parse(@expected_SDF).to_json,
45
+ JSON.parse(@document.to_SDF).to_json
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Inquisitio
4
+ class IndexerTest < Minitest::Test
5
+ def setup
6
+ @document_endpoint = 'http://my.document-endpoint.com'
7
+ Inquisitio.config.document_endpoint = @document_endpoint
8
+ #def initialize(type, id, version, fields)
9
+ @documents = [Document.new("add", "12345", 1, {})]
10
+ end
11
+
12
+ def teardown
13
+ Excon.stubs.clear
14
+ end
15
+
16
+ def test_initialization
17
+ indexer = Indexer.new(@documents)
18
+ refute indexer.nil?
19
+ end
20
+
21
+ def test_indexer_should_raise_exception_if_documents_nil
22
+ assert_raises(InquisitioError, "Documents is nil") do
23
+ Indexer.index(nil)
24
+ end
25
+ end
26
+
27
+ def test_indexer_should_raise_exception_if_documents_empty
28
+ assert_raises(InquisitioError, "Documents is empty") do
29
+ Indexer.index([])
30
+ end
31
+ end
32
+
33
+ def test_create_correct_index_url
34
+ indexer = Indexer.new(@documents)
35
+ expected_url = 'http://my.document-endpoint.com/2011-02-01/documents/batch'
36
+ assert_equal expected_url, indexer.send(:batch_index_url)
37
+ end
38
+
39
+ def test_create_correct_body
40
+ doc1 = mock()
41
+ doc1.expects(:to_SDF).returns("sdf1")
42
+ doc2 = mock()
43
+ doc2.expects(:to_SDF).returns("sdf2")
44
+ doc3 = mock()
45
+ doc3.expects(:to_SDF).returns("sdf3")
46
+
47
+ documents = [ doc1, doc2, doc3 ]
48
+ indexer = Indexer.new(documents)
49
+ expected_body = '[sdf1, sdf2, sdf3]'
50
+ assert_equal expected_body, indexer.send(:body)
51
+ end
52
+
53
+ def test_index_raises_exception_when_response_not_200
54
+ Excon.defaults[:mock] = true
55
+ Excon.stub({}, {:body => 'Bad Happened', :status => 500})
56
+
57
+ indexer = Indexer.new(@documents)
58
+
59
+ assert_raises(InquisitioError, "Indexer failed with status code 500") do
60
+ indexer.index
61
+ end
62
+ end
63
+
64
+ def test_index_returns_results
65
+ body = 'Some Body'
66
+ Excon.defaults[:mock] = true
67
+ Excon.stub({}, {:body => body, :status => 200})
68
+
69
+ indexer = Indexer.new(@documents)
70
+ response = indexer.index
71
+ assert_equal body, response
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Inquisitio
4
+ class LoggerTest < Minitest::Test
5
+ def setup
6
+ super
7
+ @logger = Logger.new
8
+ end
9
+
10
+ def test_debug
11
+ $stdout.expects(:puts).with("foobar")
12
+ @logger.debug "foobar"
13
+ end
14
+
15
+ def test_info
16
+ $stdout.expects(:puts).with("foobar")
17
+ @logger.info "foobar"
18
+ end
19
+
20
+ def test_warn
21
+ $stdout.expects(:puts).with("foobar")
22
+ @logger.warn "foobar"
23
+ end
24
+
25
+ def test_error
26
+ $stderr.expects(:puts).with("foobar")
27
+ @logger.error "foobar"
28
+ end
29
+
30
+ def test_fatal
31
+ $stderr.expects(:puts).with("foobar")
32
+ @logger.fatal "foobar"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Inquisitio
4
+ class SearchUrlBuilderTest < Minitest::Test
5
+ def setup
6
+ super
7
+ @search_endpoint = 'http://my.search-endpoint.com'
8
+ Inquisitio.config.search_endpoint = @search_endpoint
9
+ Inquisitio.config.default_search_size = '10'
10
+ end
11
+
12
+ def test_create_correct_search_url_without_return_fields
13
+ url = SearchUrlBuilder.build(query: 'Star Wars')
14
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=10'
15
+ assert_equal expected_url, url
16
+ end
17
+
18
+ def test_create_correct_search_url_including_return_fields
19
+ url = SearchUrlBuilder.build(query: 'Star Wars', return_fields: [ 'title', 'year', '%' ] )
20
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&return-fields=title,year,%25&size=10'
21
+ assert_equal expected_url, url
22
+ end
23
+
24
+ def test_create_boolean_query_search_url_with_only_filters
25
+ url = SearchUrlBuilder.build(filters: {title: 'Star Wars'})
26
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20title:\'Star%20Wars\')&size=10'
27
+ assert_equal expected_url, url
28
+ end
29
+
30
+ def test_create_boolean_query_search_url_with_query_and_filters
31
+ url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: 'Animation'})
32
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&size=10'
33
+ assert_equal expected_url, url
34
+ end
35
+
36
+ def test_create_boolean_query_search_url_with_query_and_filters_and_return_fields
37
+ url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: 'Animation'}, return_fields: [ 'title', 'year', '%' ])
38
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&return-fields=title,year,%25&size=10'
39
+ assert_equal expected_url, url
40
+ end
41
+
42
+ def test_create_search_url_with_added_arguments
43
+ url = SearchUrlBuilder.build(query: 'Star Wars', filters: {genre: 'Animation'}, :arguments => { facet: 'genre', 'facet-genre-constraints' => 'Animation', 'facet-genre-top-n' => '5'})
44
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&facet=genre&facet-genre-constraints=Animation&facet-genre-top-n=5&size=10'
45
+ assert_equal expected_url, url
46
+ end
47
+
48
+ def test_create_search_url_with_default_size
49
+ url = SearchUrlBuilder.build(query: 'Star Wars')
50
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=10'
51
+ assert_equal expected_url, url
52
+ end
53
+
54
+ def test_create_search_url_overriding_default_size
55
+ url = SearchUrlBuilder.build(query: 'Star Wars', :arguments => { size: '200' })
56
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?q=Star%20Wars&size=200'
57
+ assert_equal expected_url, url
58
+ end
59
+
60
+ def test_create_correct_search_url_with_sanatised_query_string
61
+ url = SearchUrlBuilder.build(query: 'Star\' Wars', filters: {genre: 'Anim\'ation'}, :arguments => { facet: 'ge\'nre', 'facet-genr\'e-constraints' => 'Anim\'ation', 'facet-gen\'re-top-n' => '\'5'}, return_fields: [ 't\'itle', 'y\'ear' ])
62
+ expected_url = 'http://my.search-endpoint.com/2011-02-01/search?bq=(and%20\'Star%20Wars\'%20genre:\'Animation\')&return-fields=title,year&facet=genre&facet-genre-constraints=Animation&facet-genre-top-n=5&size=10'
63
+ assert_equal expected_url, url
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,90 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module Inquisitio
4
+ class SearcherTest < Minitest::Test
5
+ def setup
6
+ super
7
+ @search_endpoint = 'http://my.search-endpoint.com'
8
+ Inquisitio.config.search_endpoint = @search_endpoint
9
+ @expected_result_1 = {'id' => 1, 'title' => "Foobar", 'type' => "cat"}
10
+ @expected_result_2 = {'id' => 2, 'title' => "Foobar2", 'type' => "dog"}
11
+ @expected_results = [@expected_result_1, @expected_result_2]
12
+
13
+ body = <<-EOS
14
+ {"rank":"-text_relevance","match-expr":"(label 'star wars')","hits":{"found":2,"start":0,"hit":#{@expected_results.to_json}},"info":{"rid":"9d3b24b0e3399866dd8d376a7b1e0f6e930d55830b33a474bfac11146e9ca1b3b8adf0141a93ecee","time-ms":3,"cpu-time-ms":0}}
15
+ EOS
16
+
17
+ Excon.defaults[:mock] = true
18
+ Excon.stub({}, {body: body, status: 200})
19
+ end
20
+
21
+ def teardown
22
+ super
23
+ Excon.stubs.clear
24
+ end
25
+
26
+ def test_initialization_with_string
27
+ filters = { :genre => [ 'Animation' ] }
28
+ return_fields = [ 'title' ]
29
+ searcher = Searcher.new('Star Wars', filters.merge({return_fields: return_fields}))
30
+ assert_equal 'Star Wars', searcher.instance_variable_get("@query")
31
+ assert_equal filters, searcher.instance_variable_get("@filters")
32
+ assert_equal return_fields, searcher.instance_variable_get("@return_fields")
33
+ end
34
+
35
+ def test_initialization_with_hash
36
+ filters = { :genre => [ 'Animation' ] }
37
+ return_fields = [ 'title' ]
38
+ searcher = Searcher.new(filters.merge({return_fields: return_fields}))
39
+ assert_equal nil, searcher.instance_variable_get("@query")
40
+ assert_equal filters, searcher.instance_variable_get("@filters")
41
+ assert_equal return_fields, searcher.instance_variable_get("@return_fields")
42
+ end
43
+
44
+ def test_searcher_should_raise_exception_if_query_null
45
+ assert_raises(InquisitioError, "Query is nil") do
46
+ Searcher.search(nil)
47
+ end
48
+ end
49
+
50
+
51
+ def test_search_raises_exception_when_response_not_200
52
+ Excon.stub({}, {:body => 'Bad Happened', :status => 500})
53
+
54
+ searcher = Searcher.new('Star Wars')
55
+
56
+ assert_raises(InquisitioError, "Search failed with status code 500") do
57
+ searcher.search
58
+ end
59
+ end
60
+
61
+ def test_search_should_set_results
62
+ searcher = Searcher.new('Star Wars', { :return_fields => [ 'title', 'year', '%' ] } )
63
+ searcher.search
64
+ assert_equal @expected_results, searcher.instance_variable_get("@results")
65
+ end
66
+
67
+ def test_search_should_set_ids
68
+ searcher = Searcher.new('Star Wars', { :return_fields => [ 'title', 'year', '%' ] } )
69
+ searcher.search
70
+ assert_equal @expected_results.map{|r|r['id']}, searcher.ids
71
+ end
72
+
73
+ def test_search_should_set_records
74
+ searcher = Searcher.new('Star Wars', { :return_fields => [ 'title', 'year', '%' ] } )
75
+ searcher.search
76
+
77
+ # [{"MediaFile" => 1}, {...}]
78
+ records = []
79
+ records << {@expected_result_1['type'] => @expected_result_1['id']}
80
+ records << {@expected_result_2['type'] => @expected_result_2['id']}
81
+ assert_equal records, searcher.records
82
+ end
83
+
84
+ def test_search_calls_search_url_builder
85
+ SearchUrlBuilder.any_instance.expects(build: "http://www.example.com")
86
+ searcher = Searcher.new('Star Wars')
87
+ searcher.search
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,24 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
4
+ gem "minitest"
5
+ require "minitest/autorun"
6
+ require "minitest/pride"
7
+ require "minitest/mock"
8
+ require "mocha/setup"
9
+
10
+ lib = File.expand_path('../../lib', __FILE__)
11
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
12
+
13
+ require "inquisitio"
14
+
15
+ class Minitest::Test
16
+ def setup
17
+ Inquisitio.config do |config|
18
+ config.search_endpoint = "test-search-endpoint"
19
+
20
+ config.logger.stubs(:debug)
21
+ config.logger.stubs(:error)
22
+ end
23
+ end
24
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquisitio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-21 00:00:00.000000000 Z
11
+ date: 2013-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: excon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.25.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.25.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -28,32 +42,97 @@ dependencies:
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - '>='
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
32
60
  - !ruby/object:Gem::Version
33
61
  version: '0'
34
62
  type: :development
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
- - - '>='
66
+ - - ! '>='
39
67
  - !ruby/object:Gem::Version
40
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 5.0.8
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 5.0.8
41
97
  description: A Ruby Gem that wraps search for CloudSearch
42
98
  email:
43
99
  - jeremy@meducation.net
44
- executables: []
100
+ executables:
101
+ - boolean_query
102
+ - facet_query
103
+ - index
104
+ - search
45
105
  extensions: []
46
106
  extra_rdoc_files: []
47
107
  files:
48
108
  - .gitignore
109
+ - CHANGELOG.md
49
110
  - CONTRIBUTING.md
50
111
  - Gemfile
51
112
  - LICENCE.md
52
113
  - README.md
53
114
  - Rakefile
115
+ - bin/boolean_query
116
+ - bin/facet_query
117
+ - bin/index
118
+ - bin/search
54
119
  - inquisitio.gemspec
55
120
  - lib/inquisitio.rb
121
+ - lib/inquisitio/configuration.rb
122
+ - lib/inquisitio/document.rb
123
+ - lib/inquisitio/indexer.rb
124
+ - lib/inquisitio/inquisitio_error.rb
125
+ - lib/inquisitio/logger.rb
126
+ - lib/inquisitio/search_url_builder.rb
127
+ - lib/inquisitio/searcher.rb
56
128
  - lib/inquisitio/version.rb
129
+ - test/configuration_test.rb
130
+ - test/document_test.rb
131
+ - test/indexer_test.rb
132
+ - test/logger_test.rb
133
+ - test/search_url_builder_test.rb
134
+ - test/searcher_test.rb
135
+ - test/test_helper.rb
57
136
  homepage: https://github.com/meducation/inquisition
58
137
  licenses:
59
138
  - AGPL3
@@ -64,12 +143,12 @@ require_paths:
64
143
  - lib
65
144
  required_ruby_version: !ruby/object:Gem::Requirement
66
145
  requirements:
67
- - - '>='
146
+ - - ! '>='
68
147
  - !ruby/object:Gem::Version
69
148
  version: '0'
70
149
  required_rubygems_version: !ruby/object:Gem::Requirement
71
150
  requirements:
72
- - - '>='
151
+ - - ! '>='
73
152
  - !ruby/object:Gem::Version
74
153
  version: '0'
75
154
  requirements: []
@@ -78,5 +157,12 @@ rubygems_version: 2.1.9
78
157
  signing_key:
79
158
  specification_version: 4
80
159
  summary: This wraps AWS CloudSearch in a Ruby Gem
81
- test_files: []
160
+ test_files:
161
+ - test/configuration_test.rb
162
+ - test/document_test.rb
163
+ - test/indexer_test.rb
164
+ - test/logger_test.rb
165
+ - test/search_url_builder_test.rb
166
+ - test/searcher_test.rb
167
+ - test/test_helper.rb
82
168
  has_rdoc: