Architecture - FreeUKGen/MyopicVicar GitHub Wiki
-
Rails 6.1 (
~> 6.1.7), Ruby 2.7.8. -
MongoDB via Mongoid is the primary datastore for everything — registers, places, userid_details, csvfiles, search_records, etc.
-
MySQL is present but effectively unused.
-
config/database.ymlhas to exist becauseconfig/application.rbloadsrails/all, which pulls inActiveRecord::Railtie. - Rails won't boot without a
database.yml— even a placeholder one. - Nothing in normal development actually connects to a MySQL server.
- The
refinerycmsgems that would have used it are commented out of theGemfileentirely — that CMS path is legacy and effectively dead.
-
-
Auth: Devise +
devise-encryptable.- Legacy wrinkle: the app-specific
UseridDetailmodel (role, syndicate membership, etc.) is mirrored by a separate DeviseUsermodel that actually handles login. - See UseridDetail-System for how the two stay in sync — and how they can drift.
- Legacy wrinkle: the app-specific
-
Authorization is not gem-based — no CanCanCan, no Pundit.
- It's ad hoc: string-valued
rolefields checked directly in controllers/helpers (e.g.role == 'Manage Image Server'). - There's no central policy object. Permission logic lives wherever a given controller happens to check it.
- It's ad hoc: string-valued
-
No background job queue — no Sidekiq, Resque, or DelayedJob.
- Long-running work (rebuilding
freereg_contents, importing collections, creating search indexes) runs as one-off rake tasks a developer or mentor invokes directly. - Examples:
bin/dev-load-csv-data,freereg:calculate_freereg_content— see Development-Setup. - Nothing here is an async job a web request enqueues.
- Long-running work (rebuilding
-
Testing: RSpec (
rspec-rails). -
Scale: 109 models, 88 controllers as of this writing (
app/models,app/controllers) — most of it undocumented outside this wiki.
config.template_set is the single switch that turns this codebase into one of three public sites. Valid values: freereg, freecen, freebmd. It's set once, at boot, in config/application.rb, from config/freeukgen_application.yml.
-
FreeREG — parish register transcriptions.
README.md's primary description of the app; the most actively developed skin. -
FreeCEN — census transcriptions.
freecen1_*/freecen2_*/freecen_*models — roughly 35 of the 109 models in the app belong to this cluster alone. - FreeBMD2 — birth/marriage/death records. The smallest footprint in this codebase: only 4 skin-specific views, vs. 20 for FreeREG and 31 for FreeCEN.
This is not per-request multi-tenancy. It's a single config value baked in when the process boots. In practice, each site is a separate deployment of the same repo — its own freeukgen_application.yml, its own server process — not one running app serving all three at once. README.md also notes FreeCEN's release notes live on a separate freecen_parsing branch, so the two projects aren't always even developed in lockstep on master, despite sharing this codebase.
flowchart TD
CFG["config/freeukgen_application.yml<br/>template_set: freereg | freecen | freebmd"]
CFG -->|"read once, at boot<br/>(config/application.rb)"| BOOT["Rails boot"]
BOOT --> ASSETS["1. Asset paths<br/>app/assets_freereg, _freecen, _freebmd<br/>added to config.assets.paths"]
BOOT --> VIEWS["2. View partial naming<br/>app_specific_partial appends<br/>_#{template_set} to the base name"]
BOOT --> COND["3. Inline conditionals<br/>scattered across views / helpers / models"]
ASSETS --> SITE["One deployed process,<br/>serving one skin"]
VIEWS --> SITE
COND --> SITE
SITE --> MONGO[("MongoDB via Mongoid<br/>primary datastore, actually used")]
SITE -.->|"boot-only placeholder;<br/>refinerycms gems commented out"| MYSQL[("MySQL<br/>present but unused")]
Once set, template_set fans out through the app via three different mechanisms. Worth knowing before you touch any view or shared helper:
-
Asset paths.
config/application.rbappends a skin-specific directory toconfig.assets.pathsat boot, based ontemplate_set—app/assets_freereg,app/assets_freecen, orapp/assets_freebmd. Each skin has its own images/stylesheets/javascripts tree alongside the sharedapp/assets. -
View partial naming convention.
ApplicationHelper#app_specific_partial/#app_partialappend_#{template_set}(or_search_records_#{template_set}) to a partial's base name. A view can call a "generic" partial name and silently get the skin-specific file instead — e.g._freereg_userid_details.html.erbvs._form_freecen.html.erb.- Risk: renaming a partial without checking for its
_freereg/_freecen/_freebmdsiblings will break the other two skins invisibly.
- Risk: renaming a partial without checking for its
-
Inline conditionals. Scattered directly in views, helpers, and even a few models —
case MyopicVicar::Application.config.template_set,if template_set == 'freecen', and similar.- There's no single place that owns "what's different between the skins." It's distributed across the codebase, not confined to the partial-selection mechanism above.
A brief map of FreeREG's core vocabulary. The full breakdown of these models — fields, relationships, controllers — is in FreeREG-Core-Records.
-
Register — a specific parish record book (e.g. baptisms 1813–1850 for one church) that gets transcribed. See Gazetteer-Place-Church-Register.
-
Church — belongs to a Place; owns the Registers transcribed from it.
-
Place — a location in the UK gazetteer.
- Has a
place_cachefor fast lookups. - Has a
master_place_name/toponymhistory of historical name variants.
- Has a
-
Source — the scanned-image source a transcription Assignment is drawn from. See the model chain in Transcriber-and-Coordinator-Workflow's diagram:
Source → Register → Church → Place. -
Syndicate — a volunteer transcription group. See Syndicate-System.
-
UseridDetail — the account/role model for everyone: transcriber, syndicate coordinator, county coordinator, etc. See UseridDetail-System.
FreeCEN has its own parallel vocabulary — freecen2_place, freecen2_civil_parish, freecen_individual, freecen_dwelling, etc. — not covered here.