Skip to content

Commit 5ec7532

Browse files
Merge pull request #228 from MITLibraries/use-66-tacos
Enable TACOS integration
2 parents 0baa069 + a11f6ff commit 5ec7532

File tree

18 files changed

+468
-5
lines changed

18 files changed

+468
-5
lines changed

.env.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ PRIMO_SCOPE=cdi
77
PRIMO_TAB=all
88
PRIMO_VID=01MIT_INST:MIT
99
SYNDETICS_PRIMO_URL=https://syndetics.com/index.php?client=primo
10+
TACOS_HOST=FAKE_TACOS_HOST
11+
TACOS_URL=http://FAKE_TACOS_HOST/graphql
12+
TACOS_SOURCE=FAKE_TACOS_SOURCE
1013
TIMDEX_GRAPHQL=https://FAKE_TIMDEX_HOST/graphql
1114
TIMDEX_HOST=FAKE_TIMDEX_HOST
1215
TIMDEX_INDEX=FAKE_TIMDEX_INDEX

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ mode (e.g., `GDT=false` will still enable GDT features). Note that this is curre
128128
may have unexpected consequences if applied to other TIMDEX UI apps.
129129
- `GLOBAL_ALERT`: The main functionality for this comes from our theme gem, but when set the value will be rendered as
130130
safe html above the main header of the site.
131+
- `ORIGINS`: sets origins for CORS (currently used only for TACOS API calls).
131132
- `PLATFORM_NAME`: The value set is added to the header after the MIT Libraries logo. The logic and CSS for this comes from our theme gem.
132133
- `PRIMO_TIMEOUT`: The number of seconds before a Primo request times out (default 6).
133134
- `REQUESTS_PER_PERIOD` - number of requests that can be made for general throttles per `REQUEST_PERIOD`
@@ -136,13 +137,21 @@ may have unexpected consequences if applied to other TIMDEX UI apps.
136137
- `REDIRECT_REQUEST_PERIOD`- time in minutes used along with `REDIRECT_REQUEST_PERIOD`
137138
- `SENTRY_DSN`: Client key for Sentry exception logging.
138139
- `SENTRY_ENV`: Sentry environment for the application. Defaults to 'unknown' if unset.
140+
- `TACOS_SOURCE`: If set, this value is sent to TACOS (as the `sourceSystem` value) to distinguish which application
141+
instance is sending what search traffic. Defaults to "unset" if not defined.
142+
- `TACOS_URL`: The GraphQL endpoint for the [TACOS API](https://github.com/mitlibraries/tacos/). When set, the
143+
application will log search terms to TACOS (and eventually return suggested resources that TACOS detects).
139144
- `TIMDEX_INDEX`: Name of the index, or alias, to provide to the GraphQL endpoint. Defaults to `nil` which will let TIMDEX determine the best index to use. Wildcard values can be set, for example `rdi*` would search any indexes that begin with `rdi` in the underlying OpenSearch instance behind TIMDEX.
140145
- `TIMDEX_SOURCES`: Comma-separated list of sources to display in the advanced-search source selection element. This
141146
overrides the default which is set in ApplicationHelper.
142147

143148
#### Test Environment-only Variables
144149

145150
- `SPEC_REPORTER`: Optional variable. If set, enables spec reporter style output from tests rather than minimal output.
151+
- `TACOS_HOST`: Test Env only. Used to ensure the VCR cassettes can properly scrub specific host data to make sure we
152+
get the same cassettes regardless of which host was used to generate the cassettes. This should be set to the hostname
153+
that matches `TACOS_URL`. Ex: If `TACOS_URL` is `http://localhost:3001/graphql` then `TACOS_HOST` should be
154+
`localhost:3001`.
146155
- `TIMDEX_HOST`: Test Env only. Used to ensure the VCR cassettes can properly scrub specific host data to make sure we get the same cassettes regardless of which host was used to generate the cassettes. This should be set to the host name that matches `TIMDEX_GRAPHQL`. Ex: If `TIMDEX_GRAPHQL` is `https://www.example.com/graphql` then `TIMDEX_HOST` should be `www.example.com`.
147156

148157
### Generating VCR Cassettes
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class TacosController < ApplicationController
2+
layout false
3+
4+
def analyze
5+
return unless ApplicationHelper.tacos_enabled?
6+
7+
Tacos.analyze(params[:q])
8+
end
9+
end

app/helpers/application_helper.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
module ApplicationHelper
2+
def tacos_enabled?
3+
ENV.fetch('TACOS_URL', '').present?
4+
end
5+
module_function :tacos_enabled?
6+
27
def timdex_sources
38
ENV.fetch('TIMDEX_SOURCES', timdex_source_defaults).split(',')
49
end

app/models/tacos.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
class Tacos
2+
# The tacos_client argument here is unused in production - it is provided for
3+
# our test suite so that we can mock various error conditions to ensure that
4+
# error handling happens as we intend.
5+
def self.analyze(term, tacos_client = nil)
6+
tacos_http = setup(tacos_client)
7+
query = '{ "query": "{ logSearchEvent(searchTerm: \"' + clean_term(term) + '\", sourceSystem: \"' + tacos_source + '\" ) { phrase source detectors { suggestedResources { title url } } } }" }'
8+
begin
9+
raw_response = tacos_http.timeout(http_timeout).post(tacos_url, body: query)
10+
JSON.parse(raw_response.to_s)
11+
rescue HTTP::Error
12+
{"error" => "A connection error has occurred"}
13+
rescue JSON::ParserError
14+
{"error" => "A parsing error has occurred"}
15+
end
16+
end
17+
18+
private
19+
20+
def self.clean_term(term)
21+
term.gsub('"', '\'')
22+
end
23+
24+
def self.http_timeout
25+
ENV.fetch('TIMDEX_TIMEOUT', 6).to_f
26+
end
27+
28+
def self.origins
29+
ENV.fetch('ORIGINS', nil)
30+
end
31+
32+
# We define the HTTP connection this way so that it can be overridden during
33+
# testing, to make sure that the .analyze method can handle specific error
34+
# conditions.
35+
def self.setup(tacos_client)
36+
tacos_client || HTTP.persistent(tacos_url)
37+
.headers(accept: 'application/json',
38+
'Content-Type': 'application/json',
39+
origin: origins)
40+
end
41+
42+
def self.tacos_source
43+
ENV.fetch('TACOS_SOURCE', 'timdexui_unset')
44+
end
45+
46+
def self.tacos_url
47+
ENV.fetch('TACOS_URL', nil)
48+
end
49+
end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<% return unless (tacos_enabled? and @enhanced_query[:q].present?) %>
2+
3+
<% data_url = "/analyze?q=#{URI.encode_www_form_component(@enhanced_query[:q])}" %>
4+
5+
<div class="tacos-container"
6+
data-controller="content-loader"
7+
data-content-loader-url-value=<%= data_url %>>
8+
</div>

app/views/search/results.html.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,6 @@
6868
<% end %>
6969
</div>
7070

71+
<%= render(partial: 'trigger_tacos') if tacos_enabled? %>
72+
7173
<%= javascript_include_tag "filters" %>

app/views/tacos/analyze.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!-- Result of TACOS analysis would go here -->

config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
get 'issn', to: 'fact#issn'
99
get 'pmid', to: 'fact#pmid'
1010

11+
get 'analyze', to: 'tacos#analyze'
12+
1113
get 'record/(:id)',
1214
to: 'record#view',
1315
as: 'record',

test/controllers/search_controller_test.rb

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ def setup
275275
end
276276
assert_response :success
277277

278-
assert_select('div[data-content-loader-url-value]', 0)
278+
assert_select('div[data-content-loader-url-value].fact-container', 0)
279279
end
280280
end
281281

@@ -305,7 +305,7 @@ def setup
305305

306306
assert_response :success
307307

308-
assert_select('div[data-content-loader-url-value]', 0)
308+
assert_select('div[data-content-loader-url-value].fact-container', 0)
309309
end
310310
end
311311

@@ -333,7 +333,7 @@ def setup
333333
end
334334
assert_response :success
335335

336-
assert_select('div[data-content-loader-url-value]', 0)
336+
assert_select('div[data-content-loader-url-value].fact-container', 0)
337337
end
338338
end
339339

@@ -361,7 +361,31 @@ def setup
361361
end
362362
assert_response :success
363363

364-
assert_select('div[data-content-loader-url-value]', 0)
364+
assert_select('div[data-content-loader-url-value].fact-container', 0)
365+
end
366+
end
367+
368+
test 'TACOS intervention is inserted when TACOS enabled' do
369+
VCR.use_cassette('tacos',
370+
allow_playback_repeats: true) do
371+
get '/results?q=tacos'
372+
373+
assert_response :success
374+
375+
tacos_div = assert_select('div[data-content-loader-url-value].tacos-container')
376+
assert_equal '/analyze?q=tacos', tacos_div.attribute('data-content-loader-url-value').value
377+
end
378+
end
379+
380+
test 'TACOS intervention not inserted when TACOS not enabled' do
381+
VCR.use_cassette('tacos',
382+
allow_playback_repeats: true) do
383+
ClimateControl.modify(TACOS_URL: '') do
384+
get '/results?q=tacos'
385+
end
386+
assert_response :success
387+
388+
assert_select('div[data-content-loader-url-value].tacos-container', 0)
365389
end
366390
end
367391

0 commit comments

Comments
 (0)