KPCC on Rails
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.


Build Status

SCPRv4 is the code that runs It is the fourth generation of the software for the site.


SCPRv4 is a Rails app, and runs in production on Ruby 2.1.

It connects to the following services:

  • MySQL is used as the primary datastore for CMS data.
  • Elasticsearch powers article search and display.
  • Redis is used by Resque, the queuing system used for async jobs.
  • Memcached is used in production for caching, but isn't required for development.
  • Newsroom is a small Node.js app that is used to communicate editing status inside the CMS, including the completion of import jobs inside Outpost.
  • NFS is used to make uploaded audio files available on all SCPRv4 servers.
  • Assethost is used to manage all photo and video assets for content.

Getting Started


You will need to have Ruby 2.x, MySQL(~>5.6), Elasticsearch(1.7.x), Redis, and Memcached installed on the host machine.

They can be installed natively, or you can use Docker Compose to run them as containers.

It's as easy as running docker-compose up -d mysql elasticsearch redis memcached.


Copy config/templates/secrets.yml.template to config/secrets.yml.

And install dependencies:

bundle install & npm install

After that finishes, initialize your database:

bundle exec rake db:setup

bundle exec rake db:seed

To run the development server, run rails s.

Using Production Database Backups

In the chance that you need to get a backup of the production database and use that for development/debugging, you can use the scpr/restore-percona-backup Docker image in place of the MySQL service defined in docker-compose.yml. The repo for restore-percona-backup includes instructions on how to do this.

Quick Tour

SCPRv4 basically integrates a CMS and frontend. CMS conventions are provided through Outpost, but all data models are here inside the SCPRv4 project.

And speaking of data models... there is a lot of them, and some of them might seem like they overlap.

Content Models

Before SCPRv4, there was Mercer. In Mercer, there were different models for blog entries, show segments, events and news stories, and each had very defined rules about where they could exist.

ContentBase was our effort to first make all of those content types available on the home page, and then secondly to make them far more interchangable.

Since then, ContentBase loosely evolved into the Article model. It would be fair to say that in SCPRv4, "content" is any model that can be cast as an Article.

Currently, that list includes Abstract, BlogEntry, ContentShell, Event, ExternalEpisode, ExternalSegment, NewsStory, PijQuery, ShowEpisode, and ShowSegment.

Each of these models includes a to_article function, which is used to shape the content into the standardized form that Article needs. Article objects are stored in Elasticsearch, and are used directly in various index contexts around the site.

CMS Login

User accounts for the CMS are in the AdminUser model.

If you ran bundle exec rake db:seed, database will be seeded with an AdminUser called admin with password as the password. You can log in as this user in Outpost under the /outpost route.


SCPRv4 uses two kinds of caching:

  • As-Needed Partial Caching: These are normal Rails partial caches, generated and stored on-demand when content views are generated.
  • Periodic Caches: A handful of expensive caches are computed out-of-band and updated periodically rather than on-demand. The most important is the cache for homepage content, which requires loading up all homepage content objects, sorting them by section, etc.

Rake Tasks

There are some backend tasks that are worth knowing:

  • scprv4:index_all: Index all articles and models to Elasticsearch. During normal operation these are generated as content is updated, but this task can be necessary when importing data into a new deployment.
  • scprv4:sync_remote_articles: Trigger a SyncRemoteArticles job.
  • scprv4:sync_external_programs: Trigger a SyncExternalPrograms job.
  • scprv4:fire_content_alarms: Call ContentAlarm.fire_pending to publish all pending content with a current alarm.
  • scprv4:sync_audio: Trigger AudioSync::Pending and AudioSync::Program jobs.
  • scprv4:schedule:build: Trigger a BuildRecurringSchedule job.
  • scprv4:cache: Trigger jobs to build all of the periodic caches.


SCPRv4 uses rufus-scheduler to manage periodic job execution. You can find that schedule defined in lib/tasks/scheduler.rake.

In production, scheduler runs on a worker instance.

Asset Sync

AssetSync (run via this rake task) listens to a Redis server for AssetHost to send PUB/SUB notifications that an asset has been updated. When an asset is updated externally, we need to delete our cache of it so that the newest version is picked up.

In production, assetsync runs on a worker instance.