Skip to content

Add support for Primo NDE links#367

Open
jazairi wants to merge 3 commits intomainfrom
use-367
Open

Add support for Primo NDE links#367
jazairi wants to merge 3 commits intomainfrom
use-367

Conversation

@jazairi
Copy link
Contributor

@jazairi jazairi commented Mar 6, 2026

Why these changes are being introduced:

There is a need to selectively enable the Primo NDE feature.

Relevant ticket(s):

How this addresses that need:

This adds a Primo NDE feature that allows us to enable NDE links for searches and full records. Primo links are now abstracted to a Primo Link Builder to reduce duplication.

Side effects of this change:

The Primo Link Builder is the latest example of
a service being stored in the models/ directory. We may want to consider moving our services to a
separate directory for clarity's sake.

Developer

Accessibility
  • ANDI or WAVE has been run in accordance to our guide.
  • This PR contains no changes to the view layer.
  • New issues flagged by ANDI or WAVE have been resolved.
  • New issues flagged by ANDI or WAVE have been ticketed (link in the Pull Request details above).
  • No new accessibility issues have been flagged.
New ENV
  • All new ENV is documented in README.
  • All new ENV has been added to Heroku Pipeline, Staging and Prod. (N/A: NDE feature will be added selectively, as needed)
  • ENV has not changed.
Approval beyond code review
  • UXWS/stakeholder approval has been confirmed.
  • UXWS/stakeholder review will be completed retroactively.
  • UXWS/stakeholder review is not needed.
Additional context needed to review

See the ticket for example NDE links. The links in the PR build, which has the feature enabled, should match these.

Code Reviewer

Code
  • I have confirmed that the code works as intended.
  • Any CodeClimate issues have been fixed or confirmed as
    added technical debt.
Documentation
  • The commit message is clear and follows our guidelines
    (not just this pull request message).
  • The documentation has been updated or is unnecessary.
  • New dependencies are appropriate or there were no changes.
Testing
  • There are appropriate tests covering any new functionality.
  • No additional test coverage is required.

Why these changes are being introduced:

There is a need to selectively enable the Primo NDE feature.

Relevant ticket(s):

- [USE-367](https://mitlibraries.atlassian.net/browse/USE-367)

How this addresses that need:

This adds a Primo NDE feature that allows us to enable NDE links for
searches and full records. Primo links are now abstracted to a Primo
Link Builder to reduce duplication.

Side effects of this change:

The Primo Link Builder is the latest example of
a service being stored in the `models/` directory.
We may want to consider moving our services to a
separate directory for clarity's sake.
@coveralls
Copy link

coveralls commented Mar 6, 2026

Pull Request Test Coverage Report for Build 22870066925

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 29 of 29 (100.0%) changed or added relevant lines in 4 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.03%) to 98.166%

Totals Coverage Status
Change from base Build 22584961347: 0.03%
Covered Lines: 1338
Relevant Lines: 1363

💛 - Coveralls

@mitlib mitlib temporarily deployed to timdex-ui-pi-use-367-rdwdhoc9m March 6, 2026 18:58 Inactive
@qltysh
Copy link

qltysh bot commented Mar 6, 2026

❌ 2 blocking issues (2 total)

Tool Category Rule Count
rubocop Lint Class has too many lines. [255/100] 1
rubocop Lint Method has too many lines. [11/10] 1

Copy link
Member

@JPrevost JPrevost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few questions/comments to consider before we wrap this up

search_scope: 'all',
vid: ENV.fetch('PRIMO_VID')
})
PrimoLinkBuilder.new(query_term: params[:q]).search_link
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of the builder pattern. It does a great job consolidating this logic and making it more testable.

test 'primo_search_url generates correct Primo URL' do
query = 'machine learning'
expected_url = 'https://mit.primo.exlibrisgroup.com/discovery/search?query=any%2Ccontains%2Cmachine+learning&vid=01MIT_INST%3AMIT'
expected_url = 'https://mit.primo.exlibrisgroup.com/discovery/search?query=any%2Ccontains%2Cmachine+learning&tab=all&search_scope=all&vid=01MIT_INST%3AMIT'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were the links returned by this helper previously incorrect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly. The expected url string excluded a couple of params, which I don't think are necessary, but it made sense to me to include them since Primo is such a black box.

# builder.full_record_link
# # => "https://mit.primo.exlibrisgroup.com/discovery/fulldisplay?docid=alma123&..."
class PrimoLinkBuilder
def initialize(query_term: nil, record_id: nil, context: nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be helpful to explain these input variables. While query_term and record_id are easily understandable, I'm genuinely not sure what context is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context is used for the display endpoint only and indicates whether it's Alma/local ("L") or CDI (uhh...something else). Will document.

# @param tab [String] The Primo tab parameter (default: 'all')
# @param search_scope [String] The search scope (default: 'all')
# @return [String] The complete search URL
def search_link(tab: 'all', search_scope: 'all')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason the search_link and full_record_link methods use different defaults? Is it possible they both might want to default to whatever the tab is set at unless it is not set then use all like ENV.fetch('PRIMO_TAB', 'all)?

There is good documentation as to what tab, scope, and vid do in our primo_search model. I'm not sure if the best play is to note that for details as to what they are to see that model or to copy it here. Neither are ideal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. In fact, both tab and scope can probably come from env.

end
end

test 'full_record_link generates production URL by default' do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discovery and production being used interchangeably in test names might confuse us once NDE becomes production. Suggestion: update this test to use discovery URL naming

# Test NDE link generation
require 'test_helper'

class PrimoLinkBuilderTest < ActiveSupport::TestCase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect the intent of testing the way we are here is to avoid fragile tests, but it makes me nervous not to have any full link testing. I think most of these are fine as is, but maybe one more test for each type of link "search_link|full_record_link generates a full link as expected" or something?

@jazairi jazairi requested a review from JPrevost March 9, 2026 19:00
@jazairi jazairi temporarily deployed to timdex-ui-pi-use-367-rdwdhoc9m March 9, 2026 19:01 Inactive
@jazairi
Copy link
Contributor Author

jazairi commented Mar 9, 2026

@JPrevost Let me know if the updated docs are better or worse. (I'm not sure one way or the other.)

lang: lang,
tab: tab
}
base_url + URI.encode_www_form(params)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method has too many lines. [11/10] [rubocop:Metrics/MethodLength]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants