Platform Notes
Small platform facts that don’t warrant their own page: CI, logging, feature flags, Markdownable, search, and ActiveStorage (immersive#613).
CI
The CI runs before any merge to the main branch. It does not run when other branches are pushed to, but can be run on-demand using the workflow_dispatch feature of GitHub.
Stylesheets are plain CSS served by Propshaft, so CI does not run a Sass/SCSS build step.
Logging
In development, log_bench can be used to review local logs.
log_bench log/development.log
A useful feature of logbench is the easy selection of SQL statements with variables interpolated, which can then be pasted directly into a SQL editor.

Feature Flags
Feature flags are not currently implemented in the application. This document is a reference for future implementation.
Recommended Approach
A minimal feature flag system can be implemented using a database-backed model or environment variables. See this blog post for a lightweight Rails pattern.
For a more robust solution, consider the Flipper gem which provides per-user, per-group, and percentage-based rollouts.
Markdownable
The Markdownable Concern provides an easy way to include markdown for user-facing edits. Users can edit forms using markdown in a _markdown field and it will be auto-rendered and saved to the same-named field as rendered HTML, ready to be displayed on page.
How to use it
- Include the
Markdownableconcern in the model - Add 2 fields linked by name, for example
descriptiondescription_markdowndescription
- Add form fields
description_markdownas an editable fielddescriptionas a read-only field
- Add the rendered field to the
showview
Search
Search is implemented using Ransack with ransack_memory for persisting search state across requests.
Searchable Models
Models opt in to Ransack by defining ransackable_attributes and ransackable_associations:
- User – searchable by profile fields
- Deck (
app/models/decks/deck.rb) – searchable by deck attributes - Document (
app/models/resources/documents/document.rb) – searchable by title and associations
Controller Pattern
Controllers use the standard Ransack pattern:
@q = scope.ransack(params[:q])
@results = @q.result.page(params[:page])
Some controllers build custom search params. For example, VerbsController constructs filters for lemma prefix and common flag via a build_search_params helper.
Search Views
Reusable search form partial at app/views/shared/_resource_search.html.erb accepts search_path and turbo_frame locals. Resource-specific search forms exist for:
- Decks:
app/views/decks/decks/index/_search.html.erb - Documents:
app/views/resources/documents/index/_search.html.erb - Grammar Notes:
app/views/resources/grammar_notes/index/_search.html.erb
Full-Text Search
PostgreSQL full-text search is used for sentences via a GIN index on to_tsvector('simple', sentence). See PostgreSQL documentation for index details.
References
ActiveStorage
ActiveStorage handles file uploads and attachments. In production, files are stored on AWS S3.
Storage Configuration
Defined in config/storage.yml:
| Service | Backend | Usage |
|---|---|---|
test |
Disk (tmp/storage) |
Test environment |
local |
Disk (storage/) |
Development |
amazon |
S3 (immersive-app-prd) |
Production |
S3 credentials are stored in Rails credentials (aws:access_key_id, aws:secret_access_key, aws:region, aws:bucket).
Models with Attachments
- User –
has_one_attached :profile_image(profile photo with fallback to default) - Deck –
has_one_attached :anki_deck(exported Anki deck file) - Event –
has_one_attached :event_image(event banner image)
Audio Files
Audio for sentences, conjugations, and words is generated via AWS Polly and stored on S3. The Resources::API::AttachAudioService handles audio generation and attachment. Audio URLs returned by API endpoints are signed, expiring links.
Database Tables
ActiveStorage uses three tables:
active_storage_blobs– File metadata (filename, content_type, byte_size, checksum)active_storage_attachments– Polymorphic join table (record_type, record_id, name, blob_id)active_storage_variant_records– Image variant tracking