diff --git a/.gitignore b/.gitignore
index b571213..1a572b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,14 @@
-.DS_Store
-.env
+!.keep
+*.DS_Store
+*.swo
+*.swp
/.bundle
-/.sass-cache
-/build
-/tmp
-tags
+/.env
+/.foreman
+/coverage/*
+/db/*.sqlite3
+/log/*
+/public/system
+/public/assets
+/tags
+/tmp/*
diff --git a/.ruby-version b/.ruby-version
index 7ec1d6d..c043eea 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.1.0
+2.2.1
diff --git a/.sample.env b/.sample.env
index 102817e..a194f48 100644
--- a/.sample.env
+++ b/.sample.env
@@ -1 +1,5 @@
-EVENTBRITE_ACCESS_TOKEN=changeme
+# http://ddollar.github.com/foreman/
+ASSET_HOST=localhost:3000
+HOST=localhost:3000
+RACK_ENV=development
+SECRET_KEY_BASE=development_secret
diff --git a/.travis.yml b/.travis.yml
index dfb8cdb..3ad0924 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,21 @@
-language: ruby
-rvm:
- - 2.1.0
+before_install:
+ - "echo '--colour' > ~/.rspec"
+ - "echo 'gem: --no-document' > ~/.gemrc"
+ - export DISPLAY=:99.0
+ - sh -e /etc/init.d/xvfb start
+install:
+ - bin/setup
+branches:
+ only:
+ - master
+cache:
+ - bundler
+language:
+ - ruby
notifications:
email: false
+rvm:
+ - 2.2.1
+addons:
+ postgresql: "9.3"
sudo: false
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..b952631
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,57 @@
+source "https://rubygems.org"
+
+ruby "2.2.1"
+
+gem "airbrake"
+gem "autoprefixer-rails"
+gem "bourbon", "~> 4.2.0"
+gem "coffee-rails", "~> 4.1.0"
+gem "delayed_job_active_record"
+gem "email_validator"
+gem "flutie"
+gem "high_voltage"
+gem "i18n-tasks"
+gem "jquery-rails"
+gem "neat", "~> 1.7.0"
+gem "newrelic_rpm", ">= 3.9.8"
+gem "normalize-rails", "~> 3.0.0"
+gem "pg"
+gem "rails", "4.2.1"
+gem "recipient_interceptor"
+gem "refills"
+gem "sass-rails", "~> 5.0"
+gem "simple_form"
+gem "title"
+gem "uglifier"
+gem "unicorn"
+
+group :development do
+ gem "spring"
+ gem "spring-commands-rspec"
+ gem "web-console"
+end
+
+group :development, :test do
+ gem "awesome_print"
+ gem "bundler-audit", require: false
+ gem "byebug"
+ gem "dotenv-rails"
+ gem "factory_girl_rails"
+ gem "pry-rails"
+ gem "rspec-rails", "~> 3.1.0"
+end
+
+group :test do
+ gem "capybara-webkit", ">= 1.2.0"
+ gem "database_cleaner"
+ gem "formulaic"
+ gem "launchy"
+ gem "shoulda-matchers", require: false
+ gem "simplecov", require: false
+ gem "timecop"
+ gem "webmock"
+end
+
+group :staging, :production do
+ gem "rack-timeout"
+end
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..7934897
--- /dev/null
+++ b/Procfile
@@ -0,0 +1,2 @@
+web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
+worker: bundle exec rake jobs:work
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1eef235
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# Railsbridgeboston dot org
+
+## Getting Started
+
+After you have cloned this repo, run this setup script to set up your machine
+with the necessary dependencies to run and test this app:
+
+ % ./bin/setup
+
+It assumes you have a machine equipped with Ruby, Postgres, etc. If not, set up
+your machine with [this script].
+
+[this script]: https://github.com/thoughtbot/laptop
+
+After setting up, you can run the application using [foreman]:
+
+ % foreman start
+
+If you don't have `foreman`, see [Foreman's install instructions][foreman]. It
+is [purposefully excluded from the project's `Gemfile`][exclude].
+
+[foreman]: https://github.com/ddollar/foreman
+[exclude]: https://github.com/ddollar/foreman/pull/437#issuecomment-41110407
+
+## Guidelines
+
+Use the following guides for getting things done, programming well, and
+programming in style.
+
+* [Protocol](http://github.com/thoughtbot/guides/blob/master/protocol)
+* [Best Practices](http://github.com/thoughtbot/guides/blob/master/best-practices)
+* [Style](http://github.com/thoughtbot/guides/blob/master/style)
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..4a77cd0
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,17 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Rails.application.load_tasks
+task(:default).clear
+task default: [:spec]
+
+if defined? RSpec
+ task(:spec).clear
+ RSpec::Core::RakeTask.new(:spec) do |t|
+ t.verbose = false
+ end
+end
+
+task default: "bundler:audit"
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
new file mode 100644
index 0000000..646c5ab
--- /dev/null
+++ b/app/assets/javascripts/application.js
@@ -0,0 +1,15 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// compiled file.
+//
+// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
+// about supported directives.
+//
+//= require jquery
+//= require jquery_ujs
+//= require_tree .
diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss
new file mode 100644
index 0000000..e701338
--- /dev/null
+++ b/app/assets/stylesheets/application.css.scss
@@ -0,0 +1,8 @@
+@charset "utf-8";
+
+@import "normalize-rails";
+@import "bourbon";
+@import "base/grid-settings";
+@import "neat";
+@import "base/base";
+@import "refills/flashes";
diff --git a/app/assets/stylesheets/base/_base.scss b/app/assets/stylesheets/base/_base.scss
new file mode 100644
index 0000000..ddc350d
--- /dev/null
+++ b/app/assets/stylesheets/base/_base.scss
@@ -0,0 +1,15 @@
+// Bitters 1.0.0
+// http://bitters.bourbon.io
+// Copyright 2013-2015 thoughtbot, inc.
+// MIT License
+
+@import "variables";
+
+// Neat Settings -- uncomment if using Neat -- must be imported before Neat
+// @import "grid-settings";
+
+@import "buttons";
+@import "forms";
+@import "lists";
+@import "tables";
+@import "typography";
diff --git a/app/assets/stylesheets/base/_buttons.scss b/app/assets/stylesheets/base/_buttons.scss
new file mode 100644
index 0000000..f902f60
--- /dev/null
+++ b/app/assets/stylesheets/base/_buttons.scss
@@ -0,0 +1,31 @@
+#{$all-button-inputs},
+button {
+ @include appearance(none);
+ -webkit-font-smoothing: antialiased;
+ background-color: $action-color;
+ border-radius: $base-border-radius;
+ border: none;
+ color: #fff;
+ cursor: pointer;
+ display: inline-block;
+ font-family: $base-font-family;
+ font-size: $base-font-size;
+ font-weight: 600;
+ line-height: 1;
+ padding: 0.75em 1em;
+ text-decoration: none;
+ user-select: none;
+ vertical-align: middle;
+ white-space: nowrap;
+
+ &:hover,
+ &:focus {
+ background-color: darken($action-color, 15%);
+ color: #fff;
+ }
+
+ &:disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ }
+}
diff --git a/app/assets/stylesheets/base/_forms.scss b/app/assets/stylesheets/base/_forms.scss
new file mode 100644
index 0000000..db4a796
--- /dev/null
+++ b/app/assets/stylesheets/base/_forms.scss
@@ -0,0 +1,78 @@
+fieldset {
+ background-color: lighten($base-border-color, 10%);
+ border: $base-border;
+ margin: 0 0 $small-spacing;
+ padding: $base-spacing;
+}
+
+input,
+label,
+select {
+ display: block;
+ font-family: $base-font-family;
+ font-size: $base-font-size;
+}
+
+label {
+ font-weight: 600;
+ margin-bottom: $small-spacing / 2;
+
+ &.required::after {
+ content: "*";
+ }
+
+ abbr {
+ display: none;
+ }
+}
+
+#{$all-text-inputs},
+select[multiple=multiple],
+textarea {
+ background-color: $base-background-color;
+ border: $base-border;
+ border-radius: $base-border-radius;
+ box-shadow: $form-box-shadow;
+ box-sizing: border-box;
+ font-family: $base-font-family;
+ font-size: $base-font-size;
+ margin-bottom: $base-spacing / 2;
+ padding: $base-spacing / 3;
+ transition: border-color;
+ width: 100%;
+
+ &:hover {
+ border-color: darken($base-border-color, 10%);
+ }
+
+ &:focus {
+ border-color: $action-color;
+ box-shadow: $form-box-shadow-focus;
+ outline: none;
+ }
+}
+
+textarea {
+ resize: vertical;
+}
+
+input[type="search"] {
+ @include appearance(none);
+}
+
+input[type="checkbox"],
+input[type="radio"] {
+ display: inline;
+ margin-right: $small-spacing / 2;
+}
+
+input[type="file"] {
+ padding-bottom: $small-spacing;
+ width: 100%;
+}
+
+select {
+ margin-bottom: $base-spacing;
+ max-width: 100%;
+ width: auto;
+}
diff --git a/app/assets/stylesheets/base/_grid-settings.scss b/app/assets/stylesheets/base/_grid-settings.scss
new file mode 100644
index 0000000..c42bdaf
--- /dev/null
+++ b/app/assets/stylesheets/base/_grid-settings.scss
@@ -0,0 +1,14 @@
+@import "neat-helpers"; // or "../neat/neat-helpers" when not in Rails
+
+// Neat Overrides
+// $column: 90px;
+// $gutter: 30px;
+// $grid-columns: 12;
+// $max-width: em(1088);
+
+// Neat Breakpoints
+$medium-screen: em(640);
+$large-screen: em(860);
+
+$medium-screen-up: new-breakpoint(min-width $medium-screen 4);
+$large-screen-up: new-breakpoint(min-width $large-screen 8);
diff --git a/app/assets/stylesheets/base/_lists.scss b/app/assets/stylesheets/base/_lists.scss
new file mode 100644
index 0000000..c989d90
--- /dev/null
+++ b/app/assets/stylesheets/base/_lists.scss
@@ -0,0 +1,31 @@
+ul,
+ol {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+
+ &%default-ul {
+ list-style-type: disc;
+ margin-bottom: $small-spacing;
+ padding-left: $base-spacing;
+ }
+
+ &%default-ol {
+ list-style-type: decimal;
+ margin-bottom: $small-spacing;
+ padding-left: $base-spacing;
+ }
+}
+
+dl {
+ margin-bottom: $small-spacing;
+
+ dt {
+ font-weight: bold;
+ margin-top: $small-spacing;
+ }
+
+ dd {
+ margin: 0;
+ }
+}
diff --git a/app/assets/stylesheets/base/_tables.scss b/app/assets/stylesheets/base/_tables.scss
new file mode 100644
index 0000000..8c5cc31
--- /dev/null
+++ b/app/assets/stylesheets/base/_tables.scss
@@ -0,0 +1,25 @@
+table {
+ @include font-feature-settings("kern", "liga", "tnum");
+ border-collapse: collapse;
+ margin: $small-spacing 0;
+ table-layout: fixed;
+ width: 100%;
+}
+
+th {
+ border-bottom: 1px solid darken($base-border-color, 15%);
+ font-weight: 600;
+ padding: $small-spacing 0;
+ text-align: left;
+}
+
+td {
+ border-bottom: $base-border;
+ padding: $small-spacing 0;
+}
+
+tr,
+td,
+th {
+ vertical-align: middle;
+}
diff --git a/app/assets/stylesheets/base/_typography.scss b/app/assets/stylesheets/base/_typography.scss
new file mode 100644
index 0000000..358559c
--- /dev/null
+++ b/app/assets/stylesheets/base/_typography.scss
@@ -0,0 +1,55 @@
+body {
+ @include font-feature-settings("kern", "liga", "pnum");
+ -webkit-font-smoothing: antialiased;
+ color: $base-font-color;
+ font-family: $base-font-family;
+ font-size: $base-font-size;
+ line-height: $base-line-height;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: $heading-font-family;
+ font-size: $base-font-size;
+ line-height: $heading-line-height;
+ margin: 0 0 $small-spacing;
+}
+
+p {
+ margin: 0 0 $small-spacing;
+}
+
+a {
+ color: $action-color;
+ text-decoration: none;
+ transition: color 0.1s linear;
+
+ &:active,
+ &:focus,
+ &:hover {
+ color: darken($action-color, 15%);
+ }
+
+ &:active,
+ &:focus {
+ outline: none;
+ }
+}
+
+hr {
+ border-bottom: $base-border;
+ border-left: none;
+ border-right: none;
+ border-top: none;
+ margin: $base-spacing 0;
+}
+
+img,
+picture {
+ margin: 0;
+ max-width: 100%;
+}
diff --git a/app/assets/stylesheets/base/_variables.scss b/app/assets/stylesheets/base/_variables.scss
new file mode 100644
index 0000000..7594759
--- /dev/null
+++ b/app/assets/stylesheets/base/_variables.scss
@@ -0,0 +1,35 @@
+// Typography
+$base-font-family: $helvetica;
+$heading-font-family: $base-font-family;
+
+// Font Sizes
+$base-font-size: 1em;
+
+// Line height
+$base-line-height: 1.5;
+$heading-line-height: 1.2;
+
+// Other Sizes
+$base-border-radius: 3px;
+$base-spacing: $base-line-height * 1em;
+$small-spacing: $base-spacing / 2;
+$base-z-index: 0;
+
+// Colors
+$blue: #477dca;
+$dark-gray: #333;
+$medium-gray: #999;
+$light-gray: #ddd;
+
+// Font Colors
+$base-background-color: #fff;
+$base-font-color: $dark-gray;
+$action-color: $blue;
+
+// Border
+$base-border-color: $light-gray;
+$base-border: 1px solid $base-border-color;
+
+// Forms
+$form-box-shadow: inset 0 1px 3px rgba(#000, 0.06);
+$form-box-shadow-focus: $form-box-shadow, 0 0 5px adjust-color($action-color, $lightness: -5%, $alpha: -0.3);
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 0000000..d83690e
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,5 @@
+class ApplicationController < ActionController::Base
+ # Prevent CSRF attacks by raising an exception.
+ # For APIs, you may want to use :null_session instead.
+ protect_from_forgery with: :exception
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000..de6be79
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,2 @@
+module ApplicationHelper
+end
diff --git a/app/helpers/flashes_helper.rb b/app/helpers/flashes_helper.rb
new file mode 100644
index 0000000..bef014f
--- /dev/null
+++ b/app/helpers/flashes_helper.rb
@@ -0,0 +1,5 @@
+module FlashesHelper
+ def user_facing_flashes
+ flash.to_hash.slice("alert", "error", "notice", "success")
+ end
+end
diff --git a/app/mailers/.keep b/app/mailers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/.keep b/app/models/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/views/application/_analytics.html.erb b/app/views/application/_analytics.html.erb
new file mode 100644
index 0000000..5ae6470
--- /dev/null
+++ b/app/views/application/_analytics.html.erb
@@ -0,0 +1,7 @@
+<% if ENV["SEGMENT_KEY"] %>
+
+<% end %>
diff --git a/app/views/application/_flashes.html.erb b/app/views/application/_flashes.html.erb
new file mode 100644
index 0000000..3c6a280
--- /dev/null
+++ b/app/views/application/_flashes.html.erb
@@ -0,0 +1,7 @@
+<% if flash.any? %>
+
+ <% user_facing_flashes.each do |key, value| -%>
+
<%= value %>
+ <% end -%>
+
+<% end %>
diff --git a/app/views/application/_javascript.html.erb b/app/views/application/_javascript.html.erb
new file mode 100644
index 0000000..a738f79
--- /dev/null
+++ b/app/views/application/_javascript.html.erb
@@ -0,0 +1,12 @@
+<%= javascript_include_tag :application %>
+
+<%= yield :javascript %>
+
+<%= render "analytics" %>
+
+<% if Rails.env.test? %>
+ <%= javascript_tag do %>
+ $.fx.off = true;
+ $.ajaxSetup({ async: false });
+ <% end %>
+<% end %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
new file mode 100644
index 0000000..3e38f12
--- /dev/null
+++ b/app/views/layouts/application.html.erb
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ <%#
+ Configure default and controller-, and view-specific titles in
+ config/locales/en.yml. For more see:
+ https://github.com/calebthompson/title#usage
+ %>
+ <%= title %>
+ <%= stylesheet_link_tag :application, media: "all" %>
+ <%= csrf_meta_tags %>
+
+
+ <%= render "flashes" -%>
+ <%= yield %>
+ <%= render "javascript" %>
+
+
diff --git a/app/views/pages/.keep b/app/views/pages/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 0000000..66e9889
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 0000000..5191e69
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 0000000..1724048
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 0000000..afe9811
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,36 @@
+#!/usr/bin/env sh
+
+# Set up Rails app. Run this script immediately after cloning the codebase.
+# https://github.com/thoughtbot/guides/tree/master/protocol
+
+# Exit if any subcommand fails
+set -e
+
+# Set up Ruby dependencies via Bundler
+gem install bundler --conservative
+bundle check || bundle install
+
+# Set up configurable environment variables
+if [ ! -f .env ]; then
+ cp .sample.env .env
+fi
+
+# Set up database and add any development seed data
+bundle exec rake db:setup dev:prime
+
+# Add binstubs to PATH via export PATH=".git/safe/../../bin:$PATH" in ~/.zshenv
+mkdir -p .git/safe
+
+# Pick a port for Foreman
+if ! grep --quiet --no-messages --fixed-strings 'port' .foreman; then
+ printf 'port: 4000\n' >> .foreman
+fi
+
+if ! command -v foreman > /dev/null; then
+ printf 'Foreman is not installed.\n'
+ printf 'See https://github.com/ddollar/foreman for install instructions.\n'
+fi
+
+# Only if this isn't CI
+# if [ -z "$CI" ]; then
+# fi
diff --git a/browserslist b/browserslist
new file mode 100644
index 0000000..1e8f87e
--- /dev/null
+++ b/browserslist
@@ -0,0 +1,4 @@
+Last 2 versions
+Explorer >= 9
+iOS >= 7.1
+Android >= 4.4
diff --git a/config.ru b/config.ru
new file mode 100644
index 0000000..bd83b25
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Rails.application
diff --git a/config/application.rb b/config/application.rb
new file mode 100644
index 0000000..4d9a84c
--- /dev/null
+++ b/config/application.rb
@@ -0,0 +1,50 @@
+require File.expand_path('../boot', __FILE__)
+
+require "rails"
+# Pick the frameworks you want:
+require "active_model/railtie"
+require "active_job/railtie"
+require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+require "action_view/railtie"
+require "sprockets/railtie"
+# require "rails/test_unit/railtie"
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
+
+module RailsbridgebostonDotOrg
+ class Application < Rails::Application
+ config.i18n.enforce_available_locales = true
+
+ config.generators do |generate|
+ generate.helper false
+ generate.javascript_engine false
+ generate.request_specs false
+ generate.routing_specs false
+ generate.stylesheets false
+ generate.test_framework :rspec
+ generate.view_specs false
+ end
+
+ config.action_controller.action_on_unpermitted_parameters = :raise
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Do not swallow errors in after_commit/after_rollback callbacks.
+ config.active_record.raise_in_transactional_callbacks = true
+
+ config.active_job.queue_adapter = :delayed_job
+ end
+end
diff --git a/config/boot.rb b/config/boot.rb
new file mode 100644
index 0000000..6b750f0
--- /dev/null
+++ b/config/boot.rb
@@ -0,0 +1,3 @@
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' # Set up gems listed in the Gemfile.
diff --git a/config/database.yml b/config/database.yml
new file mode 100644
index 0000000..72dbbb2
--- /dev/null
+++ b/config/database.yml
@@ -0,0 +1,12 @@
+development: &default
+ adapter: postgresql
+ database: railsbridgeboston_dot_org_development
+ encoding: utf8
+ host: localhost
+ min_messages: warning
+ pool: 2
+ timeout: 5000
+
+test:
+ <<: *default
+ database: railsbridgeboston_dot_org_test
diff --git a/config/environment.rb b/config/environment.rb
new file mode 100644
index 0000000..ee8d90d
--- /dev/null
+++ b/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the Rails application.
+require File.expand_path('../application', __FILE__)
+
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 0000000..64306e1
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,44 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Do not eager load code on boot.
+ config.eager_load = false
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = true
+ config.action_mailer.delivery_method = :test
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+ # Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
+ config.assets.debug = true
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # Adds additional error checking when serving assets at runtime.
+ # Checks for improperly declared sprockets dependencies.
+ # Raises helpful error messages.
+ config.assets.raise_runtime_errors = true
+
+ # Raises error for missing translations
+ config.action_view.raise_on_missing_translations = true
+
+ config.action_mailer.default_url_options = { host: "localhost:4000" }
+end
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 0000000..4b6d717
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,89 @@
+require Rails.root.join("config/smtp")
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
+ config.cache_classes = true
+
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both threaded web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
+ # Full error reports are disabled and caching is turned on.
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Enable Rack::Cache to put a simple HTTP cache in front of your application
+ # Add `rack-cache` to your Gemfile before enabling this.
+ # For large-scale production use, consider using a caching reverse proxy like
+ # NGINX, varnish or squid.
+ # config.action_dispatch.rack_cache = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
+ config.static_cache_control = "public, max-age=#{1.year.to_i}"
+ # Enable deflate / gzip compression of controller-generated responses
+ config.middleware.use Rack::Deflater
+
+ # Compress JavaScripts and CSS.
+ config.assets.js_compressor = :uglifier
+ # config.assets.css_compressor = :sass
+
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
+ config.assets.compile = false
+
+ # Asset digests allow you to set far-future HTTP expiration dates on all assets,
+ # yet still be able to expire them through the digest params.
+ config.assets.digest = true
+
+ # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # Use the lowest log level to ensure availability of diagnostic information
+ # when problems arise.
+ config.log_level = :debug
+
+ # Prepend all log lines with the following tags.
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups.
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production.
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ config.action_controller.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("HOST"))
+
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+ # config.action_mailer.raise_delivery_errors = false
+ config.action_mailer.delivery_method = :smtp
+ config.action_mailer.smtp_settings = SMTP_SETTINGS
+
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation cannot be found).
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners.
+ config.active_support.deprecation = :notify
+
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
+
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
+
+ config.action_mailer.default_url_options = { host: ENV.fetch("HOST") }
+end
+Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
diff --git a/config/environments/staging.rb b/config/environments/staging.rb
new file mode 100644
index 0000000..d0e0f88
--- /dev/null
+++ b/config/environments/staging.rb
@@ -0,0 +1,11 @@
+require_relative "production"
+
+Mail.register_interceptor(
+ RecipientInterceptor.new(ENV.fetch("EMAIL_RECIPIENTS"))
+)
+
+Rails.application.configure do
+ # ...
+
+ config.action_mailer.default_url_options = { host: ENV.fetch("HOST") }
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 0000000..793219d
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,46 @@
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
+ # Configure static file server for tests with Cache-Control for performance.
+ config.serve_static_files = true
+ config.static_cache_control = 'public, max-age=3600'
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Randomize the order test cases are executed.
+ config.active_support.test_order = :random
+
+ # Print deprecation notices to the stderr.
+ config.active_support.deprecation = :stderr
+
+ # Raises error for missing translations
+ config.action_view.raise_on_missing_translations = true
+
+ config.action_mailer.default_url_options = { host: "www.example.com" }
+
+ config.active_job.queue_adapter = :inline
+end
diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml
new file mode 100644
index 0000000..5380ae1
--- /dev/null
+++ b/config/i18n-tasks.yml
@@ -0,0 +1,13 @@
+search:
+ paths:
+ - "app/controllers"
+ - "app/helpers"
+ - "app/presenters"
+ - "app/views"
+
+ignore_unused:
+ - activerecord.*
+ - date.*
+ - simple_form.*
+ - time.*
+ - titles.*
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
new file mode 100644
index 0000000..13abef8
--- /dev/null
+++ b/config/initializers/assets.rb
@@ -0,0 +1,11 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = (ENV["ASSETS_VERSION"] || "1.0")
+
+# Add additional assets to the asset load path
+# Rails.application.config.assets.paths << Emoji.images_path
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
+# Rails.application.config.assets.precompile += %w( search.js )
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
new file mode 100644
index 0000000..59385cd
--- /dev/null
+++ b/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
new file mode 100644
index 0000000..7f70458
--- /dev/null
+++ b/config/initializers/cookies_serializer.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.action_dispatch.cookies_serializer = :json
diff --git a/config/initializers/disable_xml_params.rb b/config/initializers/disable_xml_params.rb
new file mode 100644
index 0000000..c24d969
--- /dev/null
+++ b/config/initializers/disable_xml_params.rb
@@ -0,0 +1,3 @@
+# Protect against injection attacks
+# http://www.kb.cert.org/vuls/id/380039
+ActionDispatch::ParamsParser::DEFAULT_PARSERS.delete(Mime::XML)
diff --git a/config/initializers/errors.rb b/config/initializers/errors.rb
new file mode 100644
index 0000000..13c1795
--- /dev/null
+++ b/config/initializers/errors.rb
@@ -0,0 +1,34 @@
+require "net/http"
+require "net/smtp"
+
+# Example:
+# begin
+# some http call
+# rescue *HTTP_ERRORS => error
+# notify_hoptoad error
+# end
+
+HTTP_ERRORS = [
+ EOFError,
+ Errno::ECONNRESET,
+ Errno::EINVAL,
+ Net::HTTPBadResponse,
+ Net::HTTPHeaderSyntaxError,
+ Net::ProtocolError,
+ Timeout::Error
+]
+
+SMTP_SERVER_ERRORS = [
+ IOError,
+ Net::SMTPAuthenticationError,
+ Net::SMTPServerBusy,
+ Net::SMTPUnknownError,
+ TimeoutError
+]
+
+SMTP_CLIENT_ERRORS = [
+ Net::SMTPFatalError,
+ Net::SMTPSyntaxError
+]
+
+SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 0000000..4a994e1
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 0000000..ac033bf
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/config/initializers/json_encoding.rb b/config/initializers/json_encoding.rb
new file mode 100644
index 0000000..292542f
--- /dev/null
+++ b/config/initializers/json_encoding.rb
@@ -0,0 +1 @@
+ActiveSupport::JSON::Encoding.time_precision = 0
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 0000000..dc18996
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
new file mode 100644
index 0000000..62c626a
--- /dev/null
+++ b/config/initializers/session_store.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.session_store :cookie_store, key: '_railsbridgeboston_dot_org_session'
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
new file mode 100644
index 0000000..33725e9
--- /dev/null
+++ b/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
new file mode 100644
index 0000000..07c3f6e
--- /dev/null
+++ b/config/locales/en.yml
@@ -0,0 +1,19 @@
+en:
+ date:
+ formats:
+ default:
+ "%m/%d/%Y"
+ with_weekday:
+ "%a %m/%d/%y"
+
+ time:
+ formats:
+ default:
+ "%a, %b %-d, %Y at %r"
+ date:
+ "%b %-d, %Y"
+ short:
+ "%B %d"
+
+ titles:
+ application: Railsbridgeboston dot org
diff --git a/config/newrelic.yml b/config/newrelic.yml
new file mode 100644
index 0000000..c7ca22b
--- /dev/null
+++ b/config/newrelic.yml
@@ -0,0 +1,34 @@
+common: &default_settings
+ app_name: "railsbridgeboston_dot_org"
+ audit_log:
+ enabled: false
+ browser_monitoring:
+ auto_instrument: true
+ capture_params: false
+ developer_mode: false
+ error_collector:
+ capture_source: true
+ enabled: true
+ ignore_errors: "ActionController::RoutingError,Sinatra::NotFound"
+ license_key: "<%= ENV["NEW_RELIC_LICENSE_KEY"] %>"
+ log_level: info
+ monitor_mode: true
+ transaction_tracer:
+ enabled: true
+ record_sql: obfuscated
+ stack_trace_threshold: 0.500
+ transaction_threshold: apdex_f
+development:
+ <<: *default_settings
+ monitor_mode: false
+ developer_mode: true
+test:
+ <<: *default_settings
+ monitor_mode: false
+production:
+ <<: *default_settings
+ monitor_mode: true
+staging:
+ <<: *default_settings
+ app_name: "railsbridgeboston_dot_org (Staging)"
+ monitor_mode: true
diff --git a/config/routes.rb b/config/routes.rb
new file mode 100644
index 0000000..1daf9a4
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,2 @@
+Rails.application.routes.draw do
+end
diff --git a/config/secrets.yml b/config/secrets.yml
new file mode 100644
index 0000000..0bfb22d
--- /dev/null
+++ b/config/secrets.yml
@@ -0,0 +1,14 @@
+default: &default
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
+
+development:
+ <<: *default
+
+test:
+ <<: *default
+
+staging:
+ <<: *default
+
+production:
+ <<: *default
diff --git a/config/smtp.rb b/config/smtp.rb
new file mode 100644
index 0000000..0440e09
--- /dev/null
+++ b/config/smtp.rb
@@ -0,0 +1,9 @@
+SMTP_SETTINGS = {
+ address: ENV.fetch("SMTP_ADDRESS"), # example: "smtp.sendgrid.net"
+ authentication: :plain,
+ domain: ENV.fetch("SMTP_DOMAIN"), # example: "heroku.com"
+ enable_starttls_auto: true,
+ password: ENV.fetch("SMTP_PASSWORD"),
+ port: "587",
+ user_name: ENV.fetch("SMTP_USERNAME")
+}
diff --git a/config/unicorn.rb b/config/unicorn.rb
new file mode 100644
index 0000000..555cf62
--- /dev/null
+++ b/config/unicorn.rb
@@ -0,0 +1,30 @@
+# https://devcenter.heroku.com/articles/rails-unicorn
+
+worker_processes (ENV["UNICORN_WORKERS"] || 3).to_i
+timeout (ENV["UNICORN_TIMEOUT"] || 15).to_i
+preload_app true
+
+before_fork do |_server, _worker|
+ Signal.trap "TERM" do
+ puts "Unicorn master intercepting TERM, sending myself QUIT instead"
+ Process.kill "QUIT", Process.pid
+ end
+
+ if defined? ActiveRecord::Base
+ ActiveRecord::Base.connection.disconnect!
+ end
+end
+
+after_fork do |_server, _worker|
+ Signal.trap "TERM" do
+ puts "Unicorn worker intercepting TERM, waiting for master to send QUIT"
+ end
+
+ if defined? ActiveRecord::Base
+ config = ActiveRecord::Base.configurations[Rails.env] ||
+ Rails.application.config.database_configuration[Rails.env]
+ config["reaping_frequency"] = (ENV["DB_REAPING_FREQUENCY"] || 10).to_i
+ config["pool"] = (ENV["DB_POOL"] || 2).to_i
+ ActiveRecord::Base.establish_connection(config)
+ end
+end
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 0000000..4edb1e8
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+#
+# Examples:
+#
+# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
+# Mayor.create(name: 'Emanuel', city: cities.first)
diff --git a/lib/assets/.keep b/lib/assets/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/lib/tasks/.keep b/lib/tasks/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/lib/tasks/bundler_audit.rake b/lib/tasks/bundler_audit.rake
new file mode 100644
index 0000000..00c1263
--- /dev/null
+++ b/lib/tasks/bundler_audit.rake
@@ -0,0 +1,12 @@
+if Rails.env.development? || Rails.env.test?
+ require "bundler/audit/cli"
+
+ namespace :bundler do
+ desc "Updates the ruby-advisory-db and runs audit"
+ task :audit do
+ %w(update check).each do |command|
+ Bundler::Audit::CLI.start [command]
+ end
+ end
+ end
+end
diff --git a/lib/tasks/development_seeds.rake b/lib/tasks/development_seeds.rake
new file mode 100644
index 0000000..b9a7a2d
--- /dev/null
+++ b/lib/tasks/development_seeds.rake
@@ -0,0 +1,12 @@
+if Rails.env.development? || Rails.env.test?
+ require "factory_girl"
+
+ namespace :dev do
+ desc "Seed data for development environment"
+ task prime: "db:setup" do
+ include FactoryGirl::Syntax::Methods
+
+ # create(:user, email: "user@example.com", password: "password")
+ end
+ end
+end
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 0000000..7b93ab6
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+ The page you were looking for doesn't exist (404)
+
+
+
+
+
+
+
+
The page you were looking for doesn't exist.
+
You may have mistyped the address or the page may have moved.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/422.html b/public/422.html
new file mode 100644
index 0000000..db2ff83
--- /dev/null
+++ b/public/422.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+ The change you wanted was rejected (422)
+
+
+
+
+
+
+
+
The change you wanted was rejected.
+
Maybe you tried to change something you didn't have access to.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/500.html b/public/500.html
new file mode 100644
index 0000000..e93b854
--- /dev/null
+++ b/public/500.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+ We're sorry, but something went wrong (500)
+
+
+
+
+
+
+
+
We're sorry, but something went wrong.
+
+
If you are the application owner check the logs for more information.
+
+
+
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..3c9c7c0
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/spec/controllers/.keep b/spec/controllers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/features/.keep b/spec/features/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/helpers/.keep b/spec/helpers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb
new file mode 100644
index 0000000..c1b7aee
--- /dev/null
+++ b/spec/i18n_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+require 'i18n/tasks'
+
+describe 'I18n' do
+ let(:i18n) { I18n::Tasks::BaseTask.new }
+ let(:missing_keys) { i18n.missing_keys }
+ let(:unused_keys) { i18n.unused_keys }
+
+ it 'does not have missing keys' do
+ expect(missing_keys).to be_empty,
+ "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
+ end
+
+ it 'does not have unused keys' do
+ expect(unused_keys).to be_empty,
+ "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
+ end
+end
diff --git a/spec/lib/.keep b/spec/lib/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
new file mode 100644
index 0000000..6897678
--- /dev/null
+++ b/spec/rails_helper.rb
@@ -0,0 +1,23 @@
+ENV["RAILS_ENV"] = "test"
+
+require File.expand_path("../../config/environment", __FILE__)
+
+require "rspec/rails"
+require "shoulda/matchers"
+
+Dir[Rails.root.join("spec/support/**/*.rb")].each { |file| require file }
+
+module Features
+ # Extend this module in spec/support/features/*.rb
+ include Formulaic::Dsl
+end
+
+RSpec.configure do |config|
+ config.include Features, type: :feature
+ config.infer_base_class_for_anonymous_controllers = false
+ config.infer_spec_type_from_file_location!
+ config.use_transactional_fixtures = false
+end
+
+ActiveRecord::Migration.maintain_test_schema!
+Capybara.javascript_driver = :webkit
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..46e4254
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,22 @@
+if ENV.fetch("COVERAGE", false)
+ require "simplecov"
+ SimpleCov.start "rails"
+end
+
+require "webmock/rspec"
+
+# http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ config.expect_with :rspec do |expectations|
+ expectations.syntax = :expect
+ end
+
+ config.mock_with :rspec do |mocks|
+ mocks.syntax = :expect
+ mocks.verify_partial_doubles = true
+ end
+
+ config.order = :random
+end
+
+WebMock.disable_net_connect!(allow_localhost: true)
diff --git a/spec/support/action_mailer.rb b/spec/support/action_mailer.rb
new file mode 100644
index 0000000..b9563a3
--- /dev/null
+++ b/spec/support/action_mailer.rb
@@ -0,0 +1,5 @@
+RSpec.configure do |config|
+ config.before(:each) do
+ ActionMailer::Base.deliveries.clear
+ end
+end
diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb
new file mode 100644
index 0000000..36dcc88
--- /dev/null
+++ b/spec/support/database_cleaner.rb
@@ -0,0 +1,21 @@
+RSpec.configure do |config|
+ config.before(:suite) do
+ DatabaseCleaner.clean_with(:deletion)
+ end
+
+ config.before(:each) do
+ DatabaseCleaner.strategy = :transaction
+ end
+
+ config.before(:each, js: true) do
+ DatabaseCleaner.strategy = :deletion
+ end
+
+ config.before(:each) do
+ DatabaseCleaner.start
+ end
+
+ config.after(:each) do
+ DatabaseCleaner.clean
+ end
+end
diff --git a/spec/support/factory_girl.rb b/spec/support/factory_girl.rb
new file mode 100644
index 0000000..eec437f
--- /dev/null
+++ b/spec/support/factory_girl.rb
@@ -0,0 +1,3 @@
+RSpec.configure do |config|
+ config.include FactoryGirl::Syntax::Methods
+end
diff --git a/spec/support/features/.keep b/spec/support/features/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/i18n.rb b/spec/support/i18n.rb
new file mode 100644
index 0000000..3d4094d
--- /dev/null
+++ b/spec/support/i18n.rb
@@ -0,0 +1,3 @@
+RSpec.configure do |config|
+ config.include AbstractController::Translation
+end
diff --git a/spec/support/matchers/.keep b/spec/support/matchers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/mixins/.keep b/spec/support/mixins/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/spec/support/shared_examples/.keep b/spec/support/shared_examples/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep
new file mode 100644
index 0000000..e69de29