Skip to content

Commit

Permalink
DEV-993 Remove rights_database Dependency
Browse files Browse the repository at this point in the history
- Add `Database` class based on `rights_database` repo/gem.
- Change `RIGHTS_DATABASE_CONNECTION_STRING` to `RIGHTS_API_DATABASE_CONNECTION_STRING` for consistency.
- Internal consistency and transparency tweaks:
  - De-abbreviate `Services[:db_connection` to `Services[:database_connection]`.
  - Re-order `SUPPORT_TABLES` to keep it alphabetical
  - Move rspec boilerplate to bottom of `spec_helper.rb`
- Add `climate_control` gem for manipulating `ENV` in new database specs.
  • Loading branch information
moseshll committed Jan 16, 2024
1 parent 6870cb7 commit c5ab7ca
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 81 deletions.
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
source "https://rubygems.org"

gem "canister"
gem "climate_control"
gem "json"
gem "mysql2"
gem "puma"
gem "rights_database", github: "hathitrust/rights_database"
gem "sequel"
gem "sinatra"
gem "sinatra-contrib"

Expand Down
13 changes: 4 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
GIT
remote: https://github.com/hathitrust/rights_database.git
revision: 2d152f9e2079a7f2997de6cc9fdb783d5ee1f030
specs:
rights_database (0.1.0)
mysql2
sequel

GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
base64 (0.1.1)
bigdecimal (3.1.4)
canister (0.9.2)
climate_control (1.2.0)
coderay (1.1.3)
diff-lcs (1.5.0)
docile (1.4.0)
Expand Down Expand Up @@ -115,12 +108,14 @@ PLATFORMS

DEPENDENCIES
canister
climate_control
json
mysql2
pry
puma
rack-test
rights_database!
rspec
sequel
simplecov
simplecov-lcov
sinatra
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ services:
- gem_cache:/gems
command: bundle exec rackup --host 0.0.0.0 -p 4567
environment:
RIGHTS_DATABASE_CONNECTION_STRING: "mysql2://ht_rights:ht_rights@mariadb/ht"
RIGHTS_API_DATABASE_CONNECTION_STRING: "mysql2://ht_rights:ht_rights@mariadb/ht"
RIGHTS_API_LOGGER_LEVEL: 1 # Logger::INFO
depends_on:
- mariadb
Expand All @@ -24,7 +24,7 @@ services:
- gem_cache:/gems
command: bash -c "/usr/local/bin/wait-for mariadb:3306 && bundle exec rspec"
environment:
RIGHTS_DATABASE_CONNECTION_STRING: "mysql2://ht_rights:ht_rights@mariadb/ht"
RIGHTS_API_DATABASE_CONNECTION_STRING: "mysql2://ht_rights:ht_rights@mariadb/ht"
depends_on:
- mariadb

Expand Down
1 change: 1 addition & 0 deletions lib/rights_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module RightsAPI
end

require "rights_api/app"
require "rights_api/database"
require "rights_api/query"
require "rights_api/result"
require "rights_api/schema"
Expand Down
46 changes: 46 additions & 0 deletions lib/rights_api/database.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require "sequel"

module RightsAPI
class Database
# .connect will take
# * a full connection string (passed here OR in the environment
# variable RIGHTS_API_DATABASE_CONNECTION_STRING)
# * a set of named arguments, drawn from those passed in and the
# environment. Arguments are those supported by Sequel.
#
# Environment variables are mapped as follows:
#
# user: RIGHTS_API_DATABASE_USER
# password: RIGHTS_API_DATABASE_PASSWORD
# host: RIGHTS_API_DATABASE_HOST
# port: RIGHTS_API_DATABASE_PORT
# database: RIGHTS_API_DATABASE_DATABASE
# adapter: RIGHTS_API_DATABASE_ADAPTER
def connect(connection_string = nil, **)
return @connection if @connection

connection_string ||= ENV["RIGHTS_API_DATABASE_CONNECTION_STRING"]
if connection_string.nil?
db_args = gather_args(**)
Sequel.connect(**db_args)
else
Sequel.connect(connection_string)
end
end

private

def gather_args(**args)
%i[user password host port database adapter].each do |arg|
args[arg] ||= ENV["RIGHTS_API_DATABASE_#{arg.to_s.upcase}"]
end

args[:host] ||= "localhost"
args[:adapter] ||= :mysql2
args[:database] ||= "ht"
args
end
end
end
2 changes: 1 addition & 1 deletion lib/rights_api/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def initialize(table_name:)
# @return [Result]
def run(id:)
schema_class = Schema.class_for name: table_name
dataset = Services[:db_connection][Schema.table_for name: table_name]
dataset = Services[:database_connection][Schema.table_for name: table_name]
if id
where = {schema_class.query_for_field(field: schema_class.primary_key) => id}
dataset = dataset.where(where)
Expand Down
11 changes: 6 additions & 5 deletions lib/rights_api/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

require "canister"
require "logger"
require "rights_database"

require_relative "database"

module RightsAPI
Services = Canister.new
Services.register(:rights_database) do
RightsDatabase
Services.register(:database) do
Database.new
end

Services.register(:logger) do
Logger.new($stdout, level: ENV.fetch("RIGHTS_API_LOGGER_LEVEL", Logger::WARN).to_i)
end

Services.register(:db_connection) do
Services[:rights_database].connect.tap do |connection|
Services.register(:database_connection) do
Services[:database].connect.tap do |connection|
connection.logger = Services[:logger]
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/integration/support_table_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
require "shared_examples"

SUPPORT_TABLES = %w[
attributes
access_profiles
access_statements
access_statements_map
attributes
reasons
sources
]
Expand Down
76 changes: 14 additions & 62 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@

require_relative "../lib/rights_api"

def app
RightsAPI::App
end

def parse_json(json)
JSON.parse(json, symbolize_names: true)
end

def rights_api_endpoint
"/v1/"
end

# BEGIN RSPEC BOILERPLATE

# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
Expand Down Expand Up @@ -62,66 +76,4 @@
# inherited by the metadata hash of host groups and examples, rather than
# triggering implicit auto-inclusion in groups with matching metadata.
config.shared_context_metadata_behavior = :apply_to_host_groups

# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
# # This allows you to limit a spec run to individual examples or groups
# # you care about by tagging them with `:focus` metadata. When nothing
# # is tagged with `:focus`, all examples get run. RSpec also provides
# # aliases for `it`, `describe`, and `context` that include `:focus`
# # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
# config.filter_run_when_matching :focus
#
# # Allows RSpec to persist some state between runs in order to support
# # the `--only-failures` and `--next-failure` CLI options. We recommend
# # you configure your source control system to ignore this file.
# config.example_status_persistence_file_path = "spec/examples.txt"
#
# # Limits the available syntax to the non-monkey patched syntax that is
# # recommended. For more details, see:
# # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode
# config.disable_monkey_patching!
#
# # This setting enables warnings. It's recommended, but in some cases may
# # be too noisy due to issues in dependencies.
# config.warnings = true
#
# # Many RSpec users commonly either run the entire suite or an individual
# # file, and it's useful to allow more verbose output when running an
# # individual spec file.
# if config.files_to_run.one?
# # Use the documentation formatter for detailed output,
# # unless a formatter has already been configured
# # (e.g. via a command-line flag).
# config.default_formatter = "doc"
# end
#
# # Print the 10 slowest examples and example groups at the
# # end of the spec run, to help surface which specs are running
# # particularly slow.
# config.profile_examples = 10
#
# # Run specs in random order to surface order dependencies. If you find an
# # order dependency and want to debug it, you can fix the order by providing
# # the seed, which is printed after each run.
# # --seed 1234
# config.order = :random
#
# # Seed global randomization in this process using the `--seed` CLI option.
# # Setting this allows you to use `--seed` to deterministically reproduce
# # test failures related to randomization by passing the same `--seed` value
# # as the one that triggered the failure.
# Kernel.srand config.seed
end

def app
RightsAPI::App
end

def parse_json(json)
JSON.parse(json, symbolize_names: true)
end

def rights_api_endpoint
"/v1/"
end
46 changes: 46 additions & 0 deletions spec/unit/database_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require "climate_control"

RSpec.describe RightsAPI::Database do
describe "#initialize" do
it "creates RightsAPI::Database instance" do
expect(described_class.new).to be_an_instance_of(RightsAPI::Database)
end
end

describe "#connect" do
it "connects with built-in connection string" do
expect(described_class.new).not_to be nil
end

it "connects with explicit connection string" do
expect(described_class.new.connect(ENV["RIGHTS_API_DATABASE_CONNECTION_STRING"])).not_to be nil
end

it "connects with connection arguments" do
ClimateControl.modify(RIGHTS_API_DATABASE_CONNECTION_STRING: nil) do
args = {
user: "ht_rights",
password: "ht_rights",
host: "mariadb",
database: "ht",
adapter: "mysql2"
}
expect(described_class.new.connect(**args)).not_to be nil
end
end

it "connects with ENV variables" do
env = {RIGHTS_API_DATABASE_CONNECTION_STRING: nil,
RIGHTS_API_DATABASE_USER: "ht_rights",
RIGHTS_API_DATABASE_PASSWORD: "ht_rights",
RIGHTS_API_DATABASE_HOST: "mariadb",
RIGHTS_API_DATABASE_DATABASE: "ht",
RIGHTS_API_DATABASE_ADAPTER: "mysql2"}
ClimateControl.modify(**env) do
expect(described_class.new.connect).not_to be nil
end
end
end
end

0 comments on commit c5ab7ca

Please sign in to comment.