- Postgresql database (or likely any RDBMS).
- Rails backend.
- Hybrid of mostly server-rendered static pages sprinkled with some Vue instances.
- Devise and Pundit authentication and authorization
- Blueprinter json serialization.
- Bulma css framework, with Buefy to integrate with Vue.
- Webpacker managing all assets, including stylesheets, images, etc.
- Bundler and Yarn (1.2) package management.
- RSpec unit, request and system specs.
- Rubocop linting based on our own customizations on top of StandardRB.
- CircleCI for continuous automated linting and testing.
- Optional Docker based local development.
We generally use rails norms and idioms, on top of which we've introduced a few supplemental patterns. These are not used in every possible case, but selectively where the code benefits from the additional abstractions, and when we've had time to refactor towards them.
- Interactors using ActiveInteraction to hold more complicated backend logic that doesn't belong in a model and would bloat a controller.
- Presenters when the model and/or view contain too much logic.
- Nested resource composition and hydration using a simplified Form. This is a little bit like the FormObject pattern but with fewer responsibilities. Of the various uses listed here, our implementation only addresses Form Object as virtual resource and Form Object as composed resource. Note that we're repurposing the aforementioned ActiveInteraction gem in our forms, mostly because it provides some convenient coercions.
- A
Context
object that provides a single point of access to thread globals such ascurrent_user
. See this PR and the discussion therein, including arguments for why we chose this solution over railsCurrentAttributes
.
- All our pages are server-rendered, but some include Vue instances. Some of these 'apps' take over small sections of a page (such as the NavBar) while others take over most of their host page. The entry point into all Vue instances can be found in this directory, and here's one example of how an instance is included on an ERB template.
- We leverage existing
pundit
policies to conditionally exclude properties during json serialization. The integration between policies and serialization blueprints is mediated by BlueprintAuthorization. - Our Contributions page supports some complex filtering, the design of which is described here.