rummageable 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/rummageable.rb +74 -0
  2. data/test/rummageable_test.rb +133 -0
  3. metadata +102 -0
@@ -0,0 +1,74 @@
1
+ require "rest_client"
2
+ require "json"
3
+ require "plek"
4
+
5
+ module Rummageable
6
+
7
+ InvalidDocument = Class.new(RuntimeError)
8
+ CHUNK_SIZE = 20
9
+
10
+ attr_writer :rummager_service_name
11
+ def rummager_service_name
12
+ @rummager_service_name || "search"
13
+ end
14
+
15
+ attr_writer :rummager_host
16
+ def rummager_host
17
+ @rummager_host || Plek.current.find(rummager_service_name)
18
+ end
19
+
20
+ attr_writer :path_prefix
21
+ def path_prefix
22
+ @path_prefix || ""
23
+ end
24
+
25
+ # documents must be either a hash (for one document) or an array of hashes
26
+ # (for multiple documents)
27
+ #
28
+ def index(documents)
29
+ documents = [documents].flatten
30
+ documents.each do |document|
31
+ validate_structure document
32
+ end
33
+ url = rummager_host + path_prefix + "/documents"
34
+ 0.step(documents.length - 1, CHUNK_SIZE).each do |i|
35
+ body = JSON.dump(documents[i, CHUNK_SIZE])
36
+ RestClient.post url, body, content_type: :json, accept: :json
37
+ end
38
+ end
39
+
40
+ def delete(link)
41
+ url = rummager_host + path_prefix + "/documents/" + CGI.escape(link)
42
+ RestClient.delete url, content_type: :json, accept: :json
43
+ end
44
+
45
+ VALID_KEYS = [
46
+ %w[title],
47
+ %w[description],
48
+ %w[format],
49
+ %w[section],
50
+ %w[link],
51
+ %w[indexable_content],
52
+ %w[additional_links title],
53
+ %w[additional_links link],
54
+ %w[additional_links link_order],
55
+ ]
56
+
57
+ def validate_structure(hash, parents=[])
58
+ hash.each do |key, value|
59
+ full_key = parents + [key]
60
+ case value
61
+ when Array
62
+ value.each do |el|
63
+ validate_structure el, full_key
64
+ end
65
+ when Hash
66
+ validate_structure value, full_key
67
+ else
68
+ raise InvalidDocument unless VALID_KEYS.include?(full_key)
69
+ end
70
+ end
71
+ end
72
+
73
+ extend self
74
+ end
@@ -0,0 +1,133 @@
1
+ require "minitest/autorun"
2
+ require "webmock/minitest"
3
+ require "rummageable"
4
+ ENV["RACK_ENV"] = "test"
5
+
6
+ class RummageableTest < MiniTest::Unit::TestCase
7
+ API = Plek.current.find("search")
8
+
9
+ def test_should_index_a_single_document_by_posting_it_as_json
10
+ document = {
11
+ "title" => "TITLE",
12
+ "description" => "DESCRIPTION",
13
+ "format" => "NAME OF FORMAT",
14
+ "section" => "NAME OF SECTION",
15
+ "link" => "/link",
16
+ "indexable_content" => "TEXT",
17
+ "additional_links" => [
18
+ {"title" => "LINK1", "link" => "/link1"},
19
+ {"title" => "LINK2", "link" => "/link2"},
20
+ ]
21
+ }
22
+ json = JSON.dump([document])
23
+
24
+ stub_request(:post, "#{API}/documents").
25
+ with(body: json).
26
+ to_return(status: 200, body: '{"status":"OK"}')
27
+
28
+ Rummageable.index(document)
29
+ end
30
+
31
+ def test_should_index_multiple_documents_by_posting_them_as_json
32
+ documents = [
33
+ {"title" => "DOC1"},
34
+ {"title" => "DOC2"}
35
+ ]
36
+ json = JSON.dump(documents)
37
+
38
+ stub_request(:post, "#{API}/documents").
39
+ with(body: json).
40
+ to_return(status: 200, body: '{"status":"OK"}')
41
+
42
+ Rummageable.index(documents)
43
+ end
44
+
45
+ def test_should_send_documents_in_batches_of_20
46
+ documents = 21.times.map { |i| {"title" => "DOC#{i}"} }
47
+
48
+ stub_request(:post, "#{API}/documents").
49
+ to_return(status: 200, body: '{"status":"OK"}')
50
+
51
+ Rummageable.index(documents)
52
+ assert_requested :post, "#{API}/documents", body: JSON.dump(documents[0, 20])
53
+ assert_requested :post, "#{API}/documents", body: JSON.dump(documents[20, 1])
54
+ end
55
+
56
+ def test_should_raise_an_exception_if_a_document_has_symbol_keys
57
+ document = {title: "TITLE"}
58
+ assert_raises Rummageable::InvalidDocument do
59
+ Rummageable.index(document)
60
+ end
61
+ end
62
+
63
+ def test_should_raise_an_exception_if_a_document_has_unrecognised_keys
64
+ document = {"foo" => "bar"}
65
+ assert_raises Rummageable::InvalidDocument do
66
+ Rummageable.index(document)
67
+ end
68
+ end
69
+
70
+ def test_should_raise_an_exception_if_a_document_has_unrecognised_nested_keys
71
+ document = {
72
+ "additional_links" => [
73
+ {"foo" => "bar"}
74
+ ]
75
+ }
76
+ assert_raises Rummageable::InvalidDocument do
77
+ Rummageable.index(document)
78
+ end
79
+ end
80
+
81
+ def test_should_post_to_rummageable_host_determined_by_rummager_service_name
82
+ document = {"title" => "TITLE"}
83
+ stub_request(:post, "#{API}/documents")
84
+ stub_request(:post, "http://whitehall-search.test.alphagov.co.uk/documents")
85
+ with_rummager_service_name("whitehall-search") do
86
+ Rummageable.index(document)
87
+ end
88
+ assert_not_requested(:post, "#{API}/documents")
89
+ assert_requested(:post, "http://whitehall-search.test.alphagov.co.uk/documents")
90
+ end
91
+
92
+ def test_should_delete_a_document_by_its_link
93
+ link = "http://example.com/foo"
94
+
95
+ stub_request(:delete, "#{API}/documents/http%3A%2F%2Fexample.com%2Ffoo").
96
+ to_return(status: 200, body: '{"status":"OK"}')
97
+
98
+ Rummageable.delete(link)
99
+ end
100
+
101
+ def test_should_delete_to_rummageable_host_determined_by_rummager_service_name
102
+ link = "http://example.com/foo"
103
+ stub_request(:delete, "#{API}/documents/http%3A%2F%2Fexample.com%2Ffoo")
104
+ stub_request(:delete, "http://whitehall-search.test.alphagov.co.uk/documents/http%3A%2F%2Fexample.com%2Ffoo")
105
+ with_rummager_service_name("whitehall-search") do
106
+ Rummageable.delete(link)
107
+ end
108
+ assert_not_requested(:delete, "#{API}/#{API}/documents/http%3A%2F%2Fexample.com%2Ffoo")
109
+ assert_requested(:delete, "http://whitehall-search.test.alphagov.co.uk/documents/http%3A%2F%2Fexample.com%2Ffoo")
110
+ end
111
+
112
+ def test_should_defer_to_plek_for_the_location_of_the_rummager_host
113
+ assert_equal Plek.current.find("search"), Rummageable.rummager_host
114
+ end
115
+
116
+ def test_should_allow_the_rummager_host_to_be_set_manually_so_that_we_can_connect_to_rummager_running_at_arbitrary_locations
117
+ Rummageable.rummager_host = "http://example.com"
118
+ assert_equal "http://example.com", Rummageable.rummager_host
119
+ ensure
120
+ Rummageable.rummager_host = nil
121
+ end
122
+
123
+ private
124
+
125
+ def with_rummager_service_name(service_name)
126
+ original_rummager_service_name = Rummageable.rummager_service_name
127
+ Rummageable.rummager_service_name = "whitehall-search"
128
+ yield
129
+ ensure
130
+ Rummageable.rummager_service_name = original_rummager_service_name
131
+ end
132
+
133
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rummageable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - GovUK Beta Team
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-12 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &70235750717760 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70235750717760
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ requirement: &70235750717320 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70235750717320
36
+ - !ruby/object:Gem::Dependency
37
+ name: plek
38
+ requirement: &70235750716900 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70235750716900
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &70235750716480 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70235750716480
58
+ - !ruby/object:Gem::Dependency
59
+ name: webmock
60
+ requirement: &70235750708840 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70235750708840
69
+ description: Mediator for apps that want their content to be in the search index
70
+ email:
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/rummageable.rb
76
+ - test/rummageable_test.rb
77
+ homepage: https://github.com/alphagov/rummageable
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.10
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Mediator for apps that want their content to be in the search index
101
+ test_files:
102
+ - test/rummageable_test.rb