Skip to content

Commit

Permalink
Merge pull request #101 from MITLibraries/tco-82-knowledge-graph
Browse files Browse the repository at this point in the history
Implement Detector, Category, DetectorCategory
  • Loading branch information
matt-bernhardt authored Sep 12, 2024
2 parents 02fc057 + b770c25 commit 3cea65a
Show file tree
Hide file tree
Showing 20 changed files with 360 additions and 16 deletions.
2 changes: 1 addition & 1 deletion app/dashboards/detector/suggested_resource_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require 'administrate/base_dashboard'

module Detector
class Detector
class SuggestedResourceDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields.
Expand Down
16 changes: 16 additions & 0 deletions app/models/category.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: categories
#
# id :integer not null, primary key
# name :string
# description :text
# created_at :datetime not null
# updated_at :datetime not null
#
class Category < ApplicationRecord
has_many :detector_categories, dependent: :destroy
has_many :detectors, through: :detector_categories
end
18 changes: 12 additions & 6 deletions app/models/detector.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# frozen_string_literal: true

# Detectors are classes that implement various algorithms that allow us to identify patterns
# within search terms.
module Detector
def self.table_name_prefix
'detector_'
end
# == Schema Information
#
# Table name: detectors
#
# id :integer not null, primary key
# name :string
# created_at :datetime not null
# updated_at :datetime not null
#
class Detector < ApplicationRecord
has_many :detector_categories, dependent: :destroy
has_many :categories, through: :detector_categories
end
6 changes: 5 additions & 1 deletion app/models/detector/journal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
# created_at :datetime not null
# updated_at :datetime not null
#
module Detector
class Detector
# Detector::Journal stores information about academic journals loaded from external sources to allow us to check our
# incoming Terms against these information
class Journal < ApplicationRecord
before_save :downcase_fields!

def self.table_name_prefix
'detector_'
end

# Identify journals in which the incoming phrase matches a Journal.name exactly
#
# @note We always store the Journal.name downcased, so we should also always downcase the phrase
Expand Down
6 changes: 5 additions & 1 deletion app/models/detector/standard_identifiers.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# frozen_string_literal: true

module Detector
class Detector
# Detector::StandardIdentifiers detects the identifiers DOI, ISBN, ISSN, PMID.
# See /docs/reference/pattern_detection_and_enhancement.md for details.
class StandardIdentifiers
attr_reader :identifiers

def self.table_name_prefix
'detector_'
end

def initialize(term)
@identifiers = {}
term_pattern_checker(term)
Expand Down
6 changes: 5 additions & 1 deletion app/models/detector/suggested_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@

require 'stringex/core_ext'

module Detector
class Detector
# Detector::SuggestedResource stores custom hints that we want to send to the
# user in response to specific strings. For example, a search for "web of
# science" should be met with our custom login link to Web of Science via MIT.
class SuggestedResource < ApplicationRecord
before_save :update_fingerprint

def self.table_name_prefix
'detector_'
end

# This exists for the before_save lifecycle hook to call the calculate_fingerprint method, to ensure that these
# records always have a correctly-calculated fingerprint. It has no arguments and returns nothing.
def update_fingerprint
Expand Down
17 changes: 17 additions & 0 deletions app/models/detector_category.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: detector_categories
#
# id :integer not null, primary key
# detector_id :integer not null
# category_id :integer not null
# confidence :float
# created_at :datetime not null
# updated_at :datetime not null
#
class DetectorCategory < ApplicationRecord
belongs_to :category
belongs_to :detector
end
11 changes: 11 additions & 0 deletions db/migrate/20240909183413_create_categories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateCategories < ActiveRecord::Migration[7.1]
def change
create_table :categories do |t|
t.string :name
t.text :description

t.timestamps
end
add_index :categories, :name, unique: true
end
end
10 changes: 10 additions & 0 deletions db/migrate/20240909183513_create_detectors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateDetectors < ActiveRecord::Migration[7.1]
def change
create_table :detectors do |t|
t.string :name

t.timestamps
end
add_index :detectors, :name, unique: true
end
end
13 changes: 13 additions & 0 deletions db/migrate/20240909183613_create_detector_categories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateDetectorCategories < ActiveRecord::Migration[7.1]
def change
create_table :detector_categories do |t|
t.belongs_to :detector, null: false, foreign_key: true
t.belongs_to :category, null: false, foreign_key: true
t.float :confidence

t.timestamps
end
add_index :detector_categories, [:detector_id, :category_id]
add_index :detector_categories, [:category_id, :detector_id]
end
end
31 changes: 30 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,56 @@
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
# MovieGenre.find_or_create_by!(name: genre_name)
# end

Rails.logger.info('Seeding DB starting')

# Categories
Category.find_or_create_by(
name: 'Informational',
description: 'A type of search where the user is looking for broad information, rather than an individual item. Also known as "open-ended" or "topical".'
)
Category.find_or_create_by(
name: 'Navigational',
description: 'A type of search where the user has a location in mind, and wants to go there. In library discovery, this should mean a URL that will not be in the searched index.'
)
Category.find_or_create_by(
name: 'Transactional',
description: 'A type of search where the user has an item in mind, and wants to get that item. Also known as "known-item".'
)

# Detectors
Detector.find_or_create_by(name: 'DOI')
Detector.find_or_create_by(name: 'ISBN')
Detector.find_or_create_by(name: 'ISSN')
Detector.find_or_create_by(name: 'PMID')
Detector.find_or_create_by(name: 'Journal')
Detector.find_or_create_by(name: 'SuggestedResource')

# DetectorCategories
DetectorCategory.find_or_create_by(
detector: Detector.find_by(name: 'DOI'),
category: Category.find_by(name: 'Transactional'),
confidence: 0.95
)
DetectorCategory.find_or_create_by(
detector: Detector.find_by(name: 'ISBN'),
category: Category.find_by(name: 'Transactional'),
confidence: 0.8
)
DetectorCategory.find_or_create_by(
detector: Detector.find_by(name: 'ISSN'),
category: Category.find_by(name: 'Transactional'),
confidence: 0.6
)
DetectorCategory.find_or_create_by(
detector: Detector.find_by(name: 'PMID'),
category: Category.find_by(name: 'Transactional'),
confidence: 0.95
)
DetectorCategory.find_or_create_by(
detector: Detector.find_by(name: 'Journal'),
category: Category.find_by(name: 'Transactional'),
confidence: 0.2
)

Rails.logger.info('Seeding DB complete')
21 changes: 21 additions & 0 deletions test/fixtures/categories.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# == Schema Information
#
# Table name: categories
#
# id :integer not null, primary key
# name :string
# description :text
# created_at :datetime not null
# updated_at :datetime not null
#
informational:
name: 'Informational'
description: '...'

navigational:
name: 'Navigational'
description: '...'

transactional:
name: 'Transactional'
description: '...'
35 changes: 35 additions & 0 deletions test/fixtures/detector_categories.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# == Schema Information
#
# Table name: detector_categories
#
# id :integer not null, primary key
# detector_id :integer not null
# category_id :integer not null
# confidence :float
# created_at :datetime not null
# updated_at :datetime not null
#
one:
detector: doi
category: transactional
confidence: 0.95

two:
detector: isbn
category: transactional
confidence: 0.95

three:
detector: issn
category: transactional
confidence: 0.95

four:
detector: pmid
category: transactional
confidence: 0.95

five:
detector: journal
category: transactional
confidence: 0.5
26 changes: 26 additions & 0 deletions test/fixtures/detectors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# == Schema Information
#
# Table name: detectors
#
# id :integer not null, primary key
# name :string
# created_at :datetime not null
# updated_at :datetime not null
#
doi:
name: 'DOI'

isbn:
name: 'ISBN'

issn:
name: 'ISSN'

pmid:
name: 'PMID'

journal:
name: 'Journal'

suggestedresource:
name: 'SuggestedResource'
48 changes: 48 additions & 0 deletions test/models/category_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: categories
#
# id :integer not null, primary key
# name :string
# description :text
# created_at :datetime not null
# updated_at :datetime not null
#
require 'test_helper'

class CategoryTest < ActiveSupport::TestCase
test 'duplicate Categories are not allowed' do
initial_count = Category.count
Category.create!(name: 'Example')
assert_equal(initial_count + 1, Category.count)

assert_raises(ActiveRecord::RecordNotUnique) do
Category.create!(name: 'Example')
end
end

test 'destroying a Category will delete associated DetectorCategories' do
category_count = Category.count
link_count = DetectorCategory.count
record = categories('transactional')
link_category = record.detector_categories.count

record.destroy

assert_equal(category_count - 1, Category.count)
assert_equal(link_count - link_category, DetectorCategory.count)
end

test 'destroying a Category will not delete associated Detectors' do
category_count = Category.count
detector_count = Detector.count
record = categories('transactional')

record.destroy

assert_equal(category_count - 1, Category.count)
assert_equal(detector_count, Detector.count)
end
end
Loading

0 comments on commit 3cea65a

Please sign in to comment.