Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Detector, Category, DetectorCategory #101

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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|
JPrevost marked this conversation as resolved.
Show resolved Hide resolved
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

Copy link
Member

Choose a reason for hiding this comment

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

Note: If these don't run automatically in our PR builds (and maybe other Heroku tiers? We can talk about that) they can be configured to do that. I haven't checked if this repo is already set to run seeds in Heroku or not, just noting it before I forget as something we can address if it doesn't work as desired.

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
JPrevost marked this conversation as resolved.
Show resolved Hide resolved
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