rummageable 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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