├── .circleci └── config.yml ├── .codeclimate.yml ├── .dockerignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc.json ├── .rspec ├── .rubocop.yml ├── .ruby-version ├── .yardopts ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Procfile ├── Procfile.dev.example ├── Procfile.docker ├── README.md ├── Rakefile ├── app ├── assets │ ├── config │ │ └── manifest.js │ ├── images │ │ └── .keep │ ├── javascripts │ │ ├── application.js │ │ └── google_analytics.js │ └── stylesheets │ │ ├── application.scss │ │ └── bootstrap_variable_overrides.scss ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── controllers │ ├── application_controller.rb │ └── concerns │ │ └── .keep ├── decorators │ └── application_decorator.rb ├── forms │ └── application_form.rb ├── helpers │ └── application_helper.rb ├── javascript │ ├── packs │ │ ├── application.js │ │ └── server_rendering.js │ ├── test │ │ └── .keep │ └── views │ │ └── .keep ├── lib │ ├── constants.rb │ ├── quick_struct.rb │ └── utilities.rb ├── mailers │ └── application_mailer.rb ├── models │ ├── account.rb │ ├── application_record.rb │ ├── concerns │ │ └── .keep │ └── user.rb ├── policies │ └── application_policy.rb ├── presenters │ └── application_presenter.rb ├── serializers │ └── .keep └── views │ ├── devise │ ├── confirmations │ │ └── new.html.erb │ ├── mailer │ │ ├── confirmation_instructions.html.erb │ │ ├── email_changed.html.erb │ │ ├── password_change.html.erb │ │ ├── reset_password_instructions.html.erb │ │ └── unlock_instructions.html.erb │ ├── passwords │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── registrations │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── sessions │ │ └── new.html.erb │ ├── shared │ │ └── _links.html.erb │ └── unlocks │ │ └── new.html.erb │ └── layouts │ ├── _favicon.html.erb │ ├── _flash.html.erb │ ├── _google_analytics.html.erb │ ├── _js_setup.html.erb │ ├── application.html.erb │ ├── mailer.html.erb │ └── mailer.text.erb ├── babel.config.js ├── bin ├── brakeman ├── build ├── bundle ├── bundle-audit ├── bundler ├── bundler-audit ├── byebug ├── chromedriver ├── chromedriver-update ├── coderay ├── configure ├── figaro ├── foreman ├── htmldiff ├── launchy ├── ldiff ├── listen ├── local_server ├── mongrel_rpm ├── newrelic ├── newrelic_cmd ├── nokogiri ├── nrdebug ├── nullalign ├── pry ├── puma ├── pumactl ├── rackup ├── rails ├── rake ├── rspec ├── rubocop ├── ruby-parse ├── ruby-prof ├── ruby-prof-check-trace ├── ruby-rewrite ├── safe_yaml ├── sass ├── sass-convert ├── scss ├── setup ├── sidekiq ├── sidekiqctl ├── sprockets ├── thor ├── tilt ├── update ├── webpack ├── webpack-dev-server ├── yard ├── yardoc ├── yarn └── yri ├── config.ru ├── config ├── application.rb ├── application.yml.example ├── boot.rb ├── cable.yml ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── application_controller_renderer.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── devise.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── new_framework_defaults_5_1.rb │ ├── new_framework_defaults_5_2.rb │ ├── new_framework_defaults_6_0.rb │ ├── new_framework_defaults_7_0.rb │ ├── permissions_policy.rb │ ├── rack_mini_profiler.rb │ ├── secure_headers.rb │ ├── sentry.rb │ ├── sidekiq.rb │ └── wrap_parameters.rb ├── locales │ ├── devise.en.yml │ └── en.yml ├── newrelic.yml ├── puma.rb ├── routes.rb ├── sidekiq.yml ├── storage.yml ├── webpack │ ├── development.js │ ├── environment.js │ ├── loaders │ │ └── typescript.js │ ├── production.js │ └── test.js └── webpacker.yml ├── db ├── migrate │ ├── 20170419034832_devise_create_users.rb │ ├── 20181003064422_rename_users_to_accounts.rb │ ├── 20181003065156_create_users.rb │ ├── 20181003072918_add_authenticatable_references_to_accounts.rb │ ├── 20220223222152_create_active_storage_tables.active_storage.rb │ ├── 20220223222236_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20220223222237_create_active_storage_variant_records.active_storage.rb │ └── 20220223222238_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb ├── schema.rb └── seeds.rb ├── docker-compose.yml ├── docker-entrypoint.sh ├── jest.config.js ├── lib ├── assets │ └── .keep ├── generators │ ├── decorator │ │ ├── USAGE │ │ ├── decorator_generator.rb │ │ └── templates │ │ │ └── decorator.rb.tt │ ├── form │ │ ├── USAGE │ │ ├── form_generator.rb │ │ └── templates │ │ │ └── form.rb.tt │ └── presenter │ │ ├── USAGE │ │ ├── presenter_generator.rb │ │ └── templates │ │ └── presenter.rb.tt ├── rack │ └── reject_trace.rb └── tasks │ └── .keep ├── log └── .keep ├── package.json ├── postcss.config.js ├── public ├── 404.html ├── 422.html ├── 500.html ├── android-chrome-144x144.png ├── android-chrome-192x192.png ├── android-chrome-36x36.png ├── android-chrome-48x48.png ├── android-chrome-72x72.png ├── android-chrome-96x96.png ├── apple-touch-icon-114x114.png ├── apple-touch-icon-120x120.png ├── apple-touch-icon-144x144.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-57x57.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-72x72.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── browserconfig.xml ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon-96x96.png ├── favicon.ico ├── manifest.json ├── mstile-144x144.png ├── mstile-150x150.png ├── mstile-310x310.png ├── mstile-70x70.png └── robots.txt ├── spec ├── decorators │ └── application_decorator_spec.rb ├── factories │ ├── accounts.rb │ └── users.rb ├── forms │ └── application_form_spec.rb ├── models │ └── account_spec.rb ├── policies │ └── application_policy_spec.rb ├── presenters │ └── application_presenter_spec.rb ├── rails_helper.rb ├── spec_helper.rb └── support │ ├── active_storage_helper.rb │ ├── bullet.rb │ ├── devise.rb │ ├── factory_bot.rb │ ├── helpers.rb │ ├── helpers │ ├── response_helpers.rb │ └── session_helpers.rb │ ├── shared_contexts │ └── signed_in_user.rb │ ├── shared_examples │ └── api_requests.rb │ └── shoulda_matchers.rb ├── tmp └── .keep ├── tsconfig.json ├── vendor └── .keep └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | browser-tools: circleci/browser-tools@1.2.3 5 | jobs: 6 | test: 7 | parallelism: 1 8 | working_directory: ~/src 9 | docker: 10 | - image: cimg/ruby:3.1.2-browsers 11 | environment: 12 | BUNDLE_JOBS: 1 13 | BUNDLE_RETRY: 1 14 | BUNDLE_PATH: vendor/bundle 15 | PGHOST: 127.0.0.1 16 | PGUSER: lockstep 17 | RAILS_ENV: test 18 | - image: circleci/postgres:11-alpine-ram 19 | environment: 20 | POSTGRES_DB: rails_new_test 21 | POSTGRES_USER: lockstep 22 | steps: 23 | - checkout 24 | 25 | # Install chrome / chromedriver 26 | - browser-tools/install-chrome 27 | - browser-tools/install-chromedriver 28 | - run: 29 | command: | 30 | google-chrome --version 31 | chromedriver --version 32 | name: Check install 33 | 34 | # JS bundle 35 | - restore_cache: 36 | keys: 37 | - yarn-{{ checksum "yarn.lock" }} 38 | - yarn- 39 | 40 | - run: 41 | name: Install yarn dependencies 42 | command: yarn install --frozen-lockfile 43 | 44 | - save_cache: 45 | key: yarn-{{ checksum "yarn.lock" }} 46 | paths: 47 | - node_modules 48 | - ~/.cache/yarn 49 | 50 | # Ruby gems bundle 51 | - run: 52 | name: Configure Bundler 53 | command: | 54 | BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ") 55 | gem install bundler -v ${BUNDLER_VERSION} 56 | 57 | - restore_cache: 58 | keys: 59 | - bundle-{{ checksum "Gemfile.lock" }} 60 | - bundle- 61 | 62 | - run: 63 | name: Install bundle 64 | command: bin/bundle install 65 | 66 | - save_cache: 67 | key: bundle-{{ checksum "Gemfile.lock" }} 68 | paths: 69 | - vendor/bundle 70 | 71 | - run: 72 | name: Lint Ruby/Rails 73 | command: | 74 | bundle exec rubocop --list-target-files | \ 75 | circleci tests split | \ 76 | xargs bundle exec rubocop --parallel 77 | 78 | # Brakeman is not yet compatible with Ruby 3.1 - restore this once 79 | # https://github.com/presidentbeef/brakeman/issues/1664 has 80 | # been resolved 81 | # - run: 82 | # name: Run Brakeman 83 | # command: bundle exec brakeman --rails7 84 | 85 | - run: 86 | name: Lint JavaScript 87 | command: yarn lint-check 88 | 89 | # TODO: Uncomment if using TypeScript 90 | # - run: 91 | # name: Compile TypeScript code 92 | # command: yarn tsc 93 | 94 | - run: 95 | name: Run JavaScript tests 96 | command: yarn test 97 | 98 | - run: 99 | name: Verify bundle security 100 | command: bundle exec bundle-audit check --update 101 | 102 | - run: 103 | name: Wait for DB 104 | command: dockerize -wait tcp://localhost:5432 -timeout 1m 105 | 106 | # Environment setup 107 | - run: 108 | name: Set up app environment 109 | command: cp config/application.yml.example config/application.yml 110 | 111 | - restore_cache: 112 | keys: 113 | - assets-{{ .Branch }} 114 | - assets-development 115 | 116 | # Assets precompilation requires ENV variables, so it must come after environment gets set up 117 | - run: 118 | name: Precompile assets and packs 119 | command: bundle exec rake assets:precompile 120 | 121 | - save_cache: 122 | key: assets-{{ .Branch }}-{{ epoch }} 123 | paths: 124 | - public/assets 125 | - public/packs-test 126 | - tmp/cache/assets/sprockets 127 | - tmp/cache/webpacker 128 | 129 | # Database setup 130 | - run: 131 | name: Set up database 132 | command: | 133 | bundle exec rake db:create && bundle exec rake db:schema:load 134 | 135 | # Run rspec in parallel 136 | # Set parallelism (above) to 2 or above to split tests by timings 137 | - run: 138 | name: Run tests 139 | command: | 140 | TESTFILES=$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings) 141 | bundle exec rspec \ 142 | --no-fail-fast \ 143 | --profile 10 \ 144 | --format RspecJunitFormatter \ 145 | --out test_results/rspec.xml \ 146 | --format progress \ 147 | -- ${TESTFILES} 148 | 149 | # Save test results for timing analysis 150 | - store_test_results: 151 | path: test_results 152 | 153 | # Make screenshots of failed tests available under Artifacts tab 154 | - store_artifacts: 155 | path: tmp/screenshots 156 | # deploy-master: 157 | # machine: 158 | # image: circleci/classic:latest 159 | # working_directory: ~/src 160 | # steps: 161 | # - checkout 162 | # - run: 163 | # name: Deploy Master to Heroku 164 | # command: | 165 | # git push https://heroku:${HEROKU_API_KEY}@git.heroku.com/${HEROKU_APP_NAME}-production.git master 166 | # heroku run rake db:migrate --app ${HEROKU_APP_NAME}-production 167 | # heroku restart --app ${HEROKU_APP_NAME}-production 168 | # deploy-staging: 169 | # machine: 170 | # enabled: true 171 | # working_directory: ~/src 172 | # steps: 173 | # - checkout 174 | # - run: 175 | # name: Deploy Development to Heroku 176 | # command: | 177 | # git push https://heroku:${HEROKU_API_KEY}@git.heroku.com/${HEROKU_APP_NAME}-staging.git development:master 178 | # heroku run rake db:migrate --app ${HEROKU_APP_NAME}-staging 179 | # heroku restart --app ${HEROKU_APP_NAME}-staging 180 | 181 | workflows: 182 | version: 2 183 | build-deploy: 184 | jobs: 185 | - test 186 | # - deploy-master: 187 | # requires: 188 | # - test 189 | # filters: 190 | # branches: 191 | # only: master 192 | # - deploy-staging: 193 | # requires: 194 | # - test 195 | # filters: 196 | # branches: 197 | # only: development 198 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | plugins: 3 | duplication: 4 | enabled: true 5 | config: 6 | languages: 7 | javascript: 8 | mass_threshold: 46 9 | ruby: 10 | # Inherit the default (this line is required for some reason 🤨) 11 | mass_threshold: 12 | 13 | exclude_patterns: 14 | # Code Climate defaults: 15 | - "config/" 16 | - "db/" 17 | - "dist/" 18 | - "features/" 19 | - "**/node_modules/" 20 | - "script/" 21 | - "**/spec/" 22 | - "**/test/" 23 | - "**/tests/" 24 | - "Tests/" 25 | - "**/vendor/" 26 | - "**/*_test.go" 27 | - "**/*.d.ts" 28 | # Expanded exclusions: 29 | - "babel.config.js" 30 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | \.git 2 | .dockerignore 3 | .byebug_history 4 | log/* 5 | tmp/* 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | jquery: true, 5 | }, 6 | extends: [ 7 | "plugin:import/warnings", 8 | "plugin:import/errors", 9 | "plugin:react/recommended", 10 | // Airbnb must come before prettier, so that it doesn't apply 11 | // rules conflicting with prettier's formatting style. 12 | "airbnb", 13 | "prettier", 14 | "prettier/react", 15 | "plugin:@typescript-eslint/recommended", 16 | ], 17 | globals: { 18 | ActionCable: "writable", 19 | App: "writable", 20 | google: "writable", 21 | gtag: "writable", 22 | SETTINGS: "writable", 23 | Turbolinks: "writable", 24 | }, 25 | parser: "@typescript-eslint/parser", 26 | parserOptions: { 27 | ecmaVersion: 6, 28 | sourceType: "module", 29 | ecmaFeatures: { 30 | jsx: true, 31 | modules: true, 32 | }, 33 | }, 34 | plugins: [ 35 | "jsx-a11y", 36 | "import", 37 | "react", 38 | "prettier", 39 | "react-hooks", 40 | "@typescript-eslint", 41 | ], 42 | rules: { 43 | "prettier/prettier": "error", 44 | 45 | // TODO: configure these rules as necessary 46 | // TS 47 | "@typescript-eslint/no-unused-vars": ["error"], 48 | "@typescript-eslint/no-use-before-define": ["off"], 49 | "@typescript-eslint/camelcase": ["off"], 50 | "@typescript-eslint/no-this-alias": ["warn"], 51 | "@typescript-eslint/explicit-function-return-type": "off", 52 | "@typescript-eslint/no-non-null-assertion": "off", 53 | 54 | // JS 55 | "array-callback-return": ["warn"], 56 | "arrow-body-style": ["warn"], 57 | "class-methods-use-this": ["warn"], 58 | "consistent-return": ["warn"], 59 | "dot-notation": ["warn"], 60 | "func-names": ["error"], 61 | "import/no-unresolved": ["off"], 62 | "import/order": ["warn"], 63 | "import/prefer-default-export": ["off"], 64 | "import/extensions": [ 65 | "error", 66 | "ignorePackages", 67 | { 68 | js: "never", 69 | jsx: "never", 70 | ts: "never", 71 | tsx: "never", 72 | }, 73 | ], 74 | "import/no-extraneous-dependencies": [ 75 | "error", 76 | { 77 | devDependencies: [ 78 | "**/*.test.{js,ts}", 79 | "app/javascript/test/**/*.{js,ts}", 80 | ], 81 | }, 82 | ], 83 | "jsx-a11y/anchor-is-valid": ["off"], 84 | "lines-between-class-members": [ 85 | "error", 86 | "always", 87 | { exceptAfterSingleLine: true }, 88 | ], 89 | "new-cap": ["warn"], 90 | "no-new": ["off"], 91 | "no-param-reassign": ["warn"], 92 | "no-plusplus": ["off"], 93 | "no-undef": ["warn"], 94 | "no-underscore-dangle": ["off"], 95 | "no-useless-constructor": ["off"], 96 | "prefer-destructuring": ["warn"], 97 | "react/default-props-match-prop-types": ["warn"], 98 | "react/destructuring-assignment": ["off"], 99 | "react/forbid-prop-types": ["warn"], 100 | "react/jsx-filename-extension": ["error", { extensions: [".jsx", ".tsx"] }], 101 | "react/no-access-state-in-setstate": ["warn"], 102 | "react/no-array-index-key": ["off"], 103 | "react/no-danger": ["off"], 104 | "react/no-unused-prop-types": ["warn"], 105 | "react/no-unused-state": ["warn"], 106 | "react/prefer-stateless-function": ["warn"], 107 | "react/require-default-props": ["off"], 108 | "react/sort-comp": ["off"], 109 | "no-unused-expressions": ["warn"], 110 | "react-hooks/rules-of-hooks": "error", 111 | "react-hooks/exhaustive-deps": "off", 112 | }, 113 | settings: { 114 | "import/resolver": { 115 | node: { 116 | extensions: [".js", ".jsx", ".ts", ".tsx", "es6", ""], 117 | paths: ["app/javascript"], 118 | }, 119 | }, 120 | react: { 121 | version: "detect", 122 | }, 123 | }, 124 | overrides: [ 125 | { 126 | files: ["**/*.ts", "**/*.tsx"], 127 | rules: { 128 | "react/prop-types": "off", 129 | }, 130 | }, 131 | { 132 | files: ["**/*.js", "**/*.jsx"], 133 | rules: { 134 | "@typescript-eslint/no-var-requires": ["off"], 135 | "no-use-before-define": ["error", "nofunc"], 136 | }, 137 | }, 138 | ], 139 | }; 140 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /log/* 12 | /tmp/* 13 | !/log/.keep 14 | !/tmp/.keep 15 | 16 | # Ignore uploaded files in development 17 | /storage/* 18 | 19 | /node_modules 20 | /yarn-error.log 21 | yarn-debug.log* 22 | .yarn-integrity 23 | 24 | /public/assets 25 | .byebug_history 26 | 27 | # Ignore master key for decrypting credentials and more. 28 | /config/master.key 29 | 30 | .byebug_history 31 | Procfile.dev 32 | 33 | # RubyMine settings 34 | .idea/ 35 | 36 | # Figaro 37 | config/application.yml 38 | 39 | # Webpacker 40 | /public/packs 41 | /public/packs-test 42 | 43 | # Generated yard documentation 44 | .yardoc/ 45 | doc/ 46 | 47 | # Code coverage 48 | coverage/ 49 | 50 | Gemfile.dev 51 | Gemfile.dev.lock 52 | 53 | # asdf-vm 54 | .tool-versions 55 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "trailingComma": "es5", 4 | "overrides": [ 5 | { 6 | "files": "*.{jsx,tsx}", 7 | "options": { 8 | "printWidth": 100 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require rails_helper 3 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.1.2 2 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --protected 2 | --private 3 | 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:3.1-alpine 2 | 3 | RUN apk update && apk add --update --no-cache \ 4 | # C compiler etc 5 | build-base \ 6 | # System specs 7 | chromium \ 8 | chromium-chromedriver \ 9 | # Support git sources in the Gemfile 10 | git \ 11 | # Used by ActiveStorage 12 | imagemagick \ 13 | # Dependencies for Nokogiri 14 | libxml2-dev \ 15 | libxslt-dev \ 16 | # Webpacker and friends 17 | nodejs nodejs-npm \ 18 | # Timezone data for Ruby's TZInfo library 19 | tzdata \ 20 | # Used by the pg gem 21 | postgresql-dev 22 | 23 | RUN bundle config build.nokogiri --use-system-libraries 24 | 25 | WORKDIR /app 26 | 27 | # Install JS dependencies before copying app code to use layer caching. 28 | # Note: In JS heavy apps consider an approach similar to bundler. 29 | COPY package.json ./ 30 | RUN npm install 31 | 32 | COPY . . 33 | 34 | # We use a custom script as entry point to manage our bundle cache 35 | COPY ./docker-entrypoint.sh / 36 | RUN chmod +x /docker-entrypoint.sh 37 | ENTRYPOINT ["/docker-entrypoint.sh"] 38 | 39 | # Setup environment for cached bundle 40 | ENV BUNDLE_PATH=/gems \ 41 | BUNDLE_BIN=/gems/bin \ 42 | GEM_HOME=/gems 43 | ENV PATH="${BUNDLE_BIN}:${PATH}" 44 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | git_source(:github) do |repo_name| 6 | repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/') 7 | "https://github.com/#{repo_name}.git" 8 | end 9 | 10 | # Only define Ruby version once (i.e. for Heroku) 11 | version_file = File.join(File.dirname(__FILE__), '.ruby-version') 12 | ruby File.read(version_file).strip 13 | 14 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 15 | gem 'rails', '~> 7' 16 | 17 | gem 'react-rails' 18 | 19 | gem 'webpacker' 20 | 21 | # Use postgresql as the database for Active Record 22 | gem 'pg', '~> 1.3.0' 23 | 24 | # Use Puma as the app server 25 | gem 'puma' 26 | 27 | # Use SCSS for stylesheets 28 | gem 'sass-rails' 29 | 30 | # Automatically add vendor prefixes to CSS rules 31 | gem 'autoprefixer-rails' 32 | 33 | # Turbolinks makes navigating your web application faster. 34 | # Read more: https://github.com/turbolinks/turbolinks 35 | gem 'turbolinks', '~> 5' 36 | 37 | # Application monitoring 38 | gem 'newrelic_rpm' 39 | 40 | # Authorization 41 | gem 'pundit' 42 | 43 | # Authentication 44 | gem 'devise', '~> 4.8.0' 45 | 46 | # API serialization 47 | gem 'jsonapi-serializer' 48 | 49 | # App configuration 50 | gem 'figaro' 51 | 52 | # Exception tracking 53 | gem 'sentry-rails' 54 | gem 'sentry-sidekiq' 55 | 56 | # Job queue 57 | gem 'sidekiq' 58 | 59 | # Security 60 | gem 'secure_headers', require: false 61 | 62 | # Use ActiveStorage variant 63 | # gem 'mini_magick', '~> 4.8' 64 | 65 | # Reduces boot times through caching; required in config/boot.rb 66 | gem 'bootsnap', '>= 1.1.0', require: false 67 | 68 | # Storage 69 | # gem "aws-sdk-s3", require: false 70 | 71 | # Ruby metrics 72 | gem 'barnes' 73 | 74 | group :production do 75 | # Remove this if the app is not hosted on Heroku 76 | gem 'heroku-deflater' 77 | gem 'lograge' 78 | gem 'nakayoshi_fork' 79 | gem 'rack-timeout' 80 | end 81 | 82 | group :development, :test do 83 | # Call 'binding.break' anywhere in the code to stop execution and get a debugger console 84 | gem 'debug' 85 | 86 | gem 'foreman' 87 | 88 | # Warn about n+1 queries and unused includes 89 | gem 'bullet' 90 | # Debug page speed and memory usage 91 | gem 'memory_profiler' 92 | gem 'rack-mini-profiler', require: false 93 | # Performance profiling, works with NewRelic in develop mode 94 | gem 'ruby-prof' 95 | 96 | # Use Pry instead of IRB 97 | gem 'pry-doc' 98 | gem 'pry-rails' 99 | 100 | # Documentation 101 | gem 'yard' 102 | end 103 | 104 | group :development do 105 | gem 'brakeman' 106 | # Review emails in the browser on the fly 107 | gem 'letter_opener' 108 | gem 'listen' 109 | gem 'nullalign' 110 | gem 'rubocop', require: false 111 | gem 'rubocop-performance', require: false 112 | gem 'rubocop-rails', require: false 113 | gem 'rubocop-rspec', require: false 114 | # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. 115 | gem 'web-console', '>= 3.3.0' 116 | end 117 | 118 | group :test do 119 | gem 'bundler-audit', require: false 120 | # Adds support for Capybara system testing and selenium driver 121 | gem 'capybara' 122 | # Easy installation and use of chromedriver (and others) to run system tests 123 | # with Chrome 124 | gem 'factory_bot_rails' 125 | gem 'rspec-rails' 126 | # CircleCI test metadata collection 127 | gem 'rspec_junit_formatter' 128 | gem 'selenium-webdriver' 129 | gem 'shoulda-matchers' 130 | gem 'simplecov', require: false 131 | gem 'webdrivers' 132 | gem 'webmock' 133 | end 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Lockstep Labs, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: DB_POOL=$RAILS_MAX_THREADS bundle exec puma -C config/puma.rb 2 | worker: DB_POOL=$WORKER_CONCURRENCY bundle exec sidekiq -C config/sidekiq.yml 3 | -------------------------------------------------------------------------------- /Procfile.dev.example: -------------------------------------------------------------------------------- 1 | web: bundle exec rails server -p $PORT 2 | webpack: bin/webpack-dev-server 3 | worker: bundle exec sidekiq 4 | redis: redis-server /usr/local/etc/redis.conf 5 | -------------------------------------------------------------------------------- /Procfile.docker: -------------------------------------------------------------------------------- 1 | web: bundle exec puma -C config/puma.rb 2 | webpack: bin/webpack-dev-server 3 | worker: bundle exec sidekiq -C config/sidekiq.yml 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 5 | 6 | require_relative 'config/application' 7 | 8 | Rails.application.load_tasks 9 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../javascripts .js 3 | //= link_directory ../stylesheets .css 4 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's 5 | // vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require turbolinks 14 | //= require jquery/dist/jquery 15 | //= require jquery-ujs/src/rails 16 | //= require popper.js/dist/umd/popper 17 | //= require bootstrap/dist/js/bootstrap 18 | //= require_tree . 19 | -------------------------------------------------------------------------------- /app/assets/javascripts/google_analytics.js: -------------------------------------------------------------------------------- 1 | $(document).on("turbolinks:load", () => { 2 | if ( 3 | typeof gtag === "function" && 4 | typeof SETTINGS.google_analytics_id !== "undefined" 5 | ) { 6 | gtag("config", SETTINGS.google_analytics_id, { 7 | page_path: window.location.pathname, 8 | }); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.scss: -------------------------------------------------------------------------------- 1 | @import "bootstrap_variable_overrides"; 2 | @import "bootstrap/scss/bootstrap"; 3 | -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationCable 4 | class Channel < ActionCable::Channel::Base 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationCable 4 | class Connection < ActionCable::Connection::Base 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationController < ActionController::Base 4 | include Pundit 5 | 6 | helper_method :current_user 7 | 8 | protect_from_forgery with: :exception 9 | rescue_from ActionController::InvalidAuthenticityToken do 10 | flash[:alert] = I18n.t('app.authenticity_token_expired') 11 | redirect_back fallback_location: root_path, allow_other_host: false 12 | end 13 | 14 | before_action :authenticate_account! 15 | before_action :set_sentry_user 16 | 17 | private 18 | 19 | # A shorthand for passing locals to views, avoiding implicitly passed instance 20 | # variables. 21 | # 22 | # The following calls are equivalent to each other: 23 | # render action: :new, locals: { the_anser: 42 } 24 | # expose :new, the_answer: 42 25 | # 26 | # render locals: { the_anser: 42 } 27 | # expose the_anser: 42 28 | # 29 | # @param action [Symbol] action to render, only necessary if not default 30 | # @param locals [Hash] locals to be passed to the view 31 | # @return [void] 32 | def expose(action = nil, **locals) 33 | render action: action, locals: locals 34 | end 35 | 36 | def current_user 37 | @current_user ||= current_account&.authenticatable 38 | end 39 | 40 | def set_sentry_user 41 | Sentry.set_user(id: current_user&.id) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/decorators/application_decorator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'forwardable' 4 | 5 | # Generic decorator base class. For view-specific decorators please use the 6 | # ApplicationPresenter base class instead. 7 | class ApplicationDecorator 8 | extend Forwardable 9 | 10 | # Forwards (and optionally renames or prefixes) methods to the wrapped object. 11 | # 12 | # @param methods [Array] the method(s) to forward 13 | # @param to [Hash] the target object for the method(s) 14 | # @param prefix [Hash] an optional prefix for method calls 15 | # @param aliases [Hash] the methods to alias 16 | # @return [void] 17 | # @example Forward some methods 18 | # forward :first_name, :last_name 19 | # @example Forward and rename a method 20 | # forward age: :user_age 21 | # @example Forward and rename at the same time 22 | # forward :first_name, :last_name, age: :user_age 23 | # @example Forward methods with a prefix 24 | # forward :first_name, prefix: :user 25 | def self.forward(*methods, to: :wrapped, prefix: nil, **aliases) 26 | if prefix 27 | methods.each do |old_name| 28 | def_delegator to, old_name, "#{prefix}_#{old_name}" 29 | end 30 | else 31 | def_delegators to, *methods 32 | end 33 | 34 | aliases.each do |old_name, new_name| 35 | def_delegator to, old_name, new_name 36 | end 37 | end 38 | 39 | # Forwards all methods to the wrapped object via method_missing. 40 | # 41 | # @note This is not recommend, prefer explicitly forwarding required methods. 42 | # @return [void] 43 | def self.forward_all 44 | define_method :method_missing do |m, *args, &block| 45 | return super(m, *args, &block) unless wrapped.respond_to?(m) 46 | 47 | wrapped.send(m, *args, &block) 48 | end 49 | 50 | define_method :respond_to_missing? do |m, include_private = false| 51 | wrapped.respond_to?(m) || super(m, include_private) 52 | end 53 | end 54 | 55 | # Wraps each object in the provided collection in a decorator instance. 56 | # 57 | # @returns [Array] 58 | def self.decorate_collection(collection) 59 | collection.map { |element| new(element) } 60 | end 61 | 62 | # Returns the wrapped object. 63 | attr_reader :wrapped 64 | 65 | # @param wrapped [Type] the object to be wrapped by the decorator 66 | def initialize(wrapped) 67 | @wrapped = wrapped 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /app/forms/application_form.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationForm 4 | include ActiveModel::Model 5 | 6 | class << self 7 | # Form attributes defined via {.attributes} 8 | # 9 | # @return [Array] 10 | attr_reader :form_attributes 11 | 12 | # Defines the attributes of the form object by using attr_accessor. 13 | # 14 | # @example 15 | # class UserForm < ApplicationForm 16 | # attributes :first_name, :last_name 17 | # end 18 | # @param attributes [Array] - the attributes available on the form 19 | # @return [void] 20 | def attributes(*attributes) 21 | @form_attributes = attributes.map do |attribute| 22 | attr_accessor attribute 23 | 24 | attribute.to_s 25 | end 26 | end 27 | 28 | # Sets or infers the resource name. 29 | # 30 | # @param klass [String] the name of the resource class 31 | # @return [Class] 32 | # @example A class where the form object name does not match the resource: 33 | # class SignupForm < ApplicationForm 34 | # resource_class User 35 | # end 36 | def resource_class(klass = nil) 37 | @resource_class ||= (klass || name.chomp('Form').constantize) 38 | end 39 | 40 | # Hook used to override model_name on child classes. 41 | # 42 | # @return [void] 43 | def inherited(child_class) 44 | super 45 | 46 | child_class.instance_eval do 47 | def model_name 48 | ActiveModel::Name.new(self, nil, resource_class.name) 49 | end 50 | end 51 | end 52 | 53 | # Returns a full set of form object and resource validators. 54 | # This is used by form libraries, such as simple_form. 55 | def validators_on(*attributes) 56 | super + resource_class.validators_on(*attributes) 57 | end 58 | end 59 | 60 | # The underlying model wrapped by the form. 61 | # 62 | # @return [Object] 63 | attr_reader :resource 64 | 65 | delegate :id, :persisted?, to: :resource 66 | 67 | # @param resource [Object] - the resource wrapped by the form 68 | # @param params [Hash{String=>Object}] - the changeset 69 | def initialize(resource = self.class.resource_class.new, params = {}) 70 | @resource = resource 71 | @params = params.to_h.with_indifferent_access 72 | .except('id', 'created_at', 'updated_at') 73 | @resource.assign_attributes(resource_attributes) 74 | super(form_attributes) 75 | end 76 | 77 | # Validates the current form object and then calls save! on the 78 | # underlying resource. 79 | # 80 | # @return [Boolean] 81 | def save 82 | unless valid? && resource.valid? 83 | errors.merge!(resource.errors) 84 | return false 85 | end 86 | resource.save! 87 | end 88 | 89 | private 90 | 91 | def resource_attributes 92 | @params.slice(*resource.attribute_names) 93 | end 94 | 95 | def form_attributes 96 | @params.slice(*self.class.form_attributes) 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | # Translate Rails standard flash keys for Bootstrap 5 | def flash_alert_class(name) 6 | case name 7 | when 'notice' then 'alert-success' 8 | when 'alert' then 'alert-danger' 9 | else name 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/javascript/packs/application.js: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/browser"; 2 | 3 | // Support component names relative to this directory: 4 | const componentRequireContext = require.context("views", true); 5 | const ReactRailsUJS = require("react_ujs"); 6 | 7 | ReactRailsUJS.useContext(componentRequireContext); 8 | 9 | Sentry.init({ 10 | dsn: SETTINGS.SENTRY_DSN_FRONTEND, 11 | }); 12 | -------------------------------------------------------------------------------- /app/javascript/packs/server_rendering.js: -------------------------------------------------------------------------------- 1 | // By default, this pack is loaded for server-side rendering. 2 | // It must expose react_ujs as `ReactRailsUJS` and prepare a require context. 3 | const componentRequireContext = require.context("views", true); 4 | const ReactRailsUJS = require("react_ujs"); 5 | 6 | ReactRailsUJS.useContext(componentRequireContext); 7 | -------------------------------------------------------------------------------- /app/javascript/test/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/app/javascript/test/.keep -------------------------------------------------------------------------------- /app/javascript/views/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/app/javascript/views/.keep -------------------------------------------------------------------------------- /app/lib/constants.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Constants 4 | HOST_URI = URI.parse(ENV.fetch('HOST')) 5 | end 6 | -------------------------------------------------------------------------------- /app/lib/quick_struct.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module QuickStruct 4 | # Shorthand alternative to Struct that gets initialized like the 5 | # now deprecated OpenStruct 6 | # 7 | # QuickStruct.new(name: 'John', age: 42) 8 | # is the same as the following syntaxes: 9 | # Struct.new(:name, :age, keyword_init: true).new(name: 'John', age: 42) 10 | # Struct.new(:name, :age).new('John', 42) 11 | def self.new(**args) 12 | Struct.new(*args.symbolize_keys.keys).new(*args.values) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/lib/utilities.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Utilities 4 | # Downloads an ActiveStorage attachement into a local tempfile and 5 | # yields it to the provided block. 6 | # 7 | # @example 8 | # Utilities.with_local_tempfile(import.file) do |file| 9 | # CSV.foreach(file) do |row| 10 | # ... 11 | # end 12 | # end 13 | # @param attached [ActiveStorage::Attached::One] the attachement to download 14 | # @return void 15 | def self.with_local_tempfile(attached) 16 | tempfile = Tempfile.new 17 | tempfile.write(attached.download) 18 | tempfile.rewind 19 | yield tempfile if block_given? 20 | ensure 21 | tempfile&.close! 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationMailer < ActionMailer::Base 4 | default from: 'from@example.com' 5 | layout 'mailer' 6 | end 7 | -------------------------------------------------------------------------------- /app/models/account.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Account < ApplicationRecord 4 | # Include default devise modules. Others available are: 5 | # :confirmable, :lockable, :timeoutable and :omniauthable 6 | devise :database_authenticatable, 7 | :registerable, 8 | :recoverable, 9 | :rememberable, 10 | :trackable, 11 | :validatable 12 | 13 | belongs_to :authenticatable, polymorphic: true 14 | 15 | private 16 | 17 | # Deliver Devise emails asynchronously. 18 | def send_devise_notification(notification, *args) 19 | devise_mailer.send(notification, self, *args).deliver_later 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | self.abstract_class = true 5 | end 6 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class User < ApplicationRecord 4 | end 5 | -------------------------------------------------------------------------------- /app/policies/application_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationPolicy 4 | attr_reader :user, :record 5 | 6 | def initialize(user, record) 7 | @user = user 8 | # Transparently unwrap presenters and decorators 9 | @record = record.respond_to?(:wrapped) ? record.wrapped : record 10 | end 11 | 12 | def index? 13 | false 14 | end 15 | 16 | def show? 17 | scope.exists?(id: record.id) 18 | end 19 | 20 | def create? 21 | false 22 | end 23 | 24 | def new? 25 | create? 26 | end 27 | 28 | def update? 29 | false 30 | end 31 | 32 | def edit? 33 | update? 34 | end 35 | 36 | def destroy? 37 | false 38 | end 39 | 40 | def scope 41 | Pundit.policy_scope!(user, record.class) 42 | end 43 | 44 | class Scope 45 | attr_reader :user, :scope 46 | 47 | def initialize(user, scope) 48 | @user = user 49 | @scope = scope 50 | end 51 | 52 | def resolve 53 | scope 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /app/presenters/application_presenter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Base class for presenters. Presenters should be limited to view-only concerns 4 | # (e.g. which text to display based on object state), and may include actual 5 | # markup tags, so ActionView::Helpers::TagHelper is included. 6 | # 7 | # Since they are view-specific treating them like better helpers™ and 8 | # invoking them in the view is fine. 9 | class ApplicationPresenter < ApplicationDecorator 10 | include ActionView::Helpers::TagHelper 11 | include AbstractController::Translation 12 | 13 | # Allows presenters to be passed directly into url helpers and dom_id 14 | forward :id, 15 | :model_name, 16 | :to_key, 17 | :to_model, 18 | :to_param, 19 | :to_partial_path 20 | 21 | # Wraps the provided object in a presenter and yields it to an optional block. 22 | # If no block is provided, this essentially behaves like .new. 23 | # 24 | # @overload call(model) 25 | # @param model [Type] the object to be wrapped by the presenter 26 | # @return [Type] the presenter instance 27 | # @example 28 | # presenter = TestPresenter.(object) 29 | # @overload call(model) 30 | # @param model [Type] the object to be wrapped by the presenter 31 | # @return [Type] the presenter instance 32 | # @yield [presenter] invokes the block with the presenter instance 33 | # @example 34 | # class TestPresenter < ApplicationPresenter 35 | # forward :meaning_of_life 36 | # end 37 | # 38 | # object = QuickStruct.new(meaning_of_life: 42) 39 | # TestPresenter.(object) do |presenter| 40 | # puts presenter.meaning_of_life 41 | # end 42 | # #=> prints 42 43 | def self.call(model) 44 | new(model).tap { |presenter| yield(presenter) if block_given? } 45 | end 46 | 47 | # Wraps all elements of the provided collection in a presenter. If a block is 48 | # provided it will be passed through to .call. 49 | # 50 | # @param models [Array] the objects to be wrapped by the presenter 51 | # @return [Array] an array of presenter instances 52 | def self.present_collection(models, &) 53 | models.map { |model| call(model, &) } 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /app/serializers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/app/serializers/.keep -------------------------------------------------------------------------------- /app/views/devise/confirmations/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend confirmation instructions

2 | 3 | <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true, value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %> 9 |
10 | 11 |
12 | <%= f.submit "Resend confirmation instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "devise/shared/links" %> 17 | -------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome <%= @email %>!

2 | 3 |

You can confirm your account email through the link below:

4 | 5 |

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

6 | -------------------------------------------------------------------------------- /app/views/devise/mailer/email_changed.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @email %>!

2 | 3 | <% if @resource.try(:unconfirmed_email?) %> 4 |

We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.

5 | <% else %> 6 |

We're contacting you to notify you that your email has been changed to <%= @resource.email %>.

7 | <% end %> 8 | -------------------------------------------------------------------------------- /app/views/devise/mailer/password_change.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

We're contacting you to notify you that your password has been changed.

4 | -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Someone has requested a link to change your password. You can do this through the link below.

4 | 5 |

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

6 | 7 |

If you didn't request this, please ignore this email.

8 |

Your password won't change until you access the link above and create a new one.

9 | -------------------------------------------------------------------------------- /app/views/devise/mailer/unlock_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

4 | 5 |

Click the link below to unlock your account:

6 | 7 |

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

8 | -------------------------------------------------------------------------------- /app/views/devise/passwords/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Change your password

2 | 3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> 4 | <%= devise_error_messages! %> 5 | <%= f.hidden_field :reset_password_token %> 6 | 7 |
8 | <%= f.label :password, "New password" %>
9 | <% if @minimum_password_length %> 10 | (<%= @minimum_password_length %> characters minimum)
11 | <% end %> 12 | <%= f.password_field :password, autofocus: true, autocomplete: "off" %> 13 |
14 | 15 |
16 | <%= f.label :password_confirmation, "Confirm new password" %>
17 | <%= f.password_field :password_confirmation, autocomplete: "off" %> 18 |
19 | 20 |
21 | <%= f.submit "Change my password" %> 22 |
23 | <% end %> 24 | 25 | <%= render "devise/shared/links" %> 26 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.erb: -------------------------------------------------------------------------------- 1 |

Forgot your password?

2 | 3 | <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.submit "Send me reset password instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "devise/shared/links" %> 17 | -------------------------------------------------------------------------------- /app/views/devise/registrations/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Edit <%= resource_name.to_s.humanize %>

2 | 3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 | <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> 12 |
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
13 | <% end %> 14 | 15 |
16 | <%= f.label :password %> (leave blank if you don't want to change it)
17 | <%= f.password_field :password, autocomplete: "off" %> 18 | <% if @minimum_password_length %> 19 |
20 | <%= @minimum_password_length %> characters minimum 21 | <% end %> 22 |
23 | 24 |
25 | <%= f.label :password_confirmation %>
26 | <%= f.password_field :password_confirmation, autocomplete: "off" %> 27 |
28 | 29 |
30 | <%= f.label :current_password %> (we need your current password to confirm your changes)
31 | <%= f.password_field :current_password, autocomplete: "off" %> 32 |
33 | 34 |
35 | <%= f.submit "Update" %> 36 |
37 | <% end %> 38 | 39 |

Cancel my account

40 | 41 |

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

42 | 43 | <%= link_to "Back", :back %> 44 | -------------------------------------------------------------------------------- /app/views/devise/registrations/new.html.erb: -------------------------------------------------------------------------------- 1 |

Sign up

2 | 3 | <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.label :password %> 13 | <% if @minimum_password_length %> 14 | (<%= @minimum_password_length %> characters minimum) 15 | <% end %>
16 | <%= f.password_field :password, autocomplete: "off" %> 17 |
18 | 19 |
20 | <%= f.label :password_confirmation %>
21 | <%= f.password_field :password_confirmation, autocomplete: "off" %> 22 |
23 | 24 |
25 | <%= f.submit "Sign up" %> 26 |
27 | <% end %> 28 | 29 | <%= render "devise/shared/links" %> 30 | -------------------------------------------------------------------------------- /app/views/devise/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 |

Log in

2 | 3 | <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> 4 |
5 | <%= f.label :email %>
6 | <%= f.email_field :email, autofocus: true %> 7 |
8 | 9 |
10 | <%= f.label :password %>
11 | <%= f.password_field :password, autocomplete: "off" %> 12 |
13 | 14 | <% if devise_mapping.rememberable? -%> 15 |
16 | <%= f.check_box :remember_me %> 17 | <%= f.label :remember_me %> 18 |
19 | <% end -%> 20 | 21 |
22 | <%= f.submit "Log in" %> 23 |
24 | <% end %> 25 | 26 | <%= render "devise/shared/links" %> 27 | -------------------------------------------------------------------------------- /app/views/devise/shared/_links.html.erb: -------------------------------------------------------------------------------- 1 | <%- if controller_name != 'sessions' %> 2 | <%= link_to "Log in", new_session_path(resource_name) %>
3 | <% end -%> 4 | 5 | <%- if devise_mapping.registerable? && controller_name != 'registrations' %> 6 | <%= link_to "Sign up", new_registration_path(resource_name) %>
7 | <% end -%> 8 | 9 | <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> 10 | <%= link_to "Forgot your password?", new_password_path(resource_name) %>
11 | <% end -%> 12 | 13 | <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> 14 | <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
15 | <% end -%> 16 | 17 | <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> 18 | <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
19 | <% end -%> 20 | 21 | <%- if devise_mapping.omniauthable? %> 22 | <%- resource_class.omniauth_providers.each do |provider| %> 23 | <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %>
24 | <% end -%> 25 | <% end -%> 26 | -------------------------------------------------------------------------------- /app/views/devise/unlocks/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend unlock instructions

2 | 3 | <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= devise_error_messages! %> 5 | 6 |
7 | <%= f.label :email %>
8 | <%= f.email_field :email, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.submit "Resend unlock instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "devise/shared/links" %> 17 | -------------------------------------------------------------------------------- /app/views/layouts/_favicon.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | <% %w(36 48 72 96 144 192).each do |size| %> 4 | " 5 | rel="icon" 6 | type="image/png" 7 | sizes="<%= "#{size}x#{size}" %>" /> 8 | <% end %> 9 | 10 | <% %w(57 60 72 76 114 120 144 152 180).each do |size| %> 11 | " 12 | rel="apple-touch-icon" 13 | type="image/png" 14 | sizes="<%= "#{size}x#{size}" %>" /> 15 | <% end %> 16 | 18 | -------------------------------------------------------------------------------- /app/views/layouts/_flash.html.erb: -------------------------------------------------------------------------------- 1 | <% if flash.present? %> 2 |
3 | <% flash.each do |name, message| %> 4 | 12 | <% end %> 13 |
14 | <% end %> 15 | -------------------------------------------------------------------------------- /app/views/layouts/_google_analytics.html.erb: -------------------------------------------------------------------------------- 1 | <% if ENV['GOOGLE_ANALYTICS_ID'].present? %> 2 | 3 | 6 | 7 | 12 | <% end %> 13 | -------------------------------------------------------------------------------- /app/views/layouts/_js_setup.html.erb: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= yield(:page_title).presence || t('app.default_title') %> 8 | 9 | <%= render partial: 'layouts/js_setup' %> 10 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 11 | <%= render partial: 'layouts/google_analytics' %> 12 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> 13 | <%= javascript_packs_with_chunks_tag 'application', 'data-turbolinks-track': 'reload' %> 14 | 15 | <%= csrf_meta_tags %> 16 | <%= render partial: 'layouts/favicon' %> 17 | 18 | 19 | 20 | 21 | <%= render partial: 'layouts/flash' %> 22 | <%= yield %> 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | var validEnv = ["development", "test", "production"]; 3 | var currentEnv = api.env(); 4 | var isProductionEnv = api.env("production"); 5 | var isTestEnv = api.env("test"); 6 | 7 | if (!validEnv.includes(currentEnv)) { 8 | throw new Error( 9 | "Please specify a valid `NODE_ENV` or " + 10 | '`BABEL_ENV` environment variables. Valid values are "development", ' + 11 | '"test", and "production". Instead, received: ' + 12 | JSON.stringify(currentEnv) + 13 | "." 14 | ); 15 | } 16 | 17 | return { 18 | // Correctly import CommonJS modules 19 | sourceType: "unambiguous", 20 | presets: [ 21 | [ 22 | "@babel/preset-env", 23 | { 24 | useBuiltIns: "usage", 25 | corejs: 3, 26 | // See https://browsersl.ist/?q=defaults for a full list of browsers 27 | // included as defaults. 28 | targets: "defaults", 29 | exclude: ["transform-typeof-symbol"], 30 | forceAllTransforms: true, 31 | modules: false, 32 | loose: true, 33 | }, 34 | ], 35 | "@babel/preset-react", 36 | "@babel/preset-typescript", 37 | ], 38 | plugins: [ 39 | "babel-plugin-macros", 40 | "@babel/plugin-syntax-dynamic-import", 41 | "@babel/plugin-transform-destructuring", 42 | ["@babel/plugin-proposal-class-properties", { loose: true }], 43 | ["@babel/plugin-proposal-object-rest-spread", { useBuiltIns: true }], 44 | [ 45 | "@babel/plugin-transform-runtime", 46 | { 47 | // NOTE: Unable to specify this since react-google-maps 48 | // depends on the old @babel/runtime 49 | // corejs: 3, 50 | helpers: false, 51 | regenerator: true, 52 | }, 53 | ], 54 | ["@babel/plugin-transform-regenerator", { async: false }], 55 | isProductionEnv && [ 56 | "babel-plugin-transform-react-remove-prop-types", 57 | { removeImport: true }, 58 | ], 59 | ["@babel/plugin-proposal-private-methods", { loose: true }], 60 | ["@babel/plugin-proposal-private-property-in-object", { loose: true }], 61 | isTestEnv && "babel-plugin-dynamic-import-node", 62 | isTestEnv && "@babel/plugin-transform-modules-commonjs", 63 | "@babel/plugin-proposal-nullish-coalescing-operator", 64 | "react-hot-loader/babel", 65 | ].filter(Boolean), 66 | }; 67 | }; 68 | -------------------------------------------------------------------------------- /bin/brakeman: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'brakeman' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("brakeman", "brakeman") 30 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'build' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("redis", "build") 30 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 || ">= 0.a" 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../../Gemfile", __FILE__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_version 64 | @bundler_version ||= begin 65 | env_var_version || cli_arg_version || 66 | lockfile_version || "#{Gem::Requirement.default}.a" 67 | end 68 | end 69 | 70 | def load_bundler! 71 | ENV["BUNDLE_GEMFILE"] ||= gemfile 72 | 73 | # must dup string for RG < 1.8 compatibility 74 | activate_bundler(bundler_version.dup) 75 | end 76 | 77 | def activate_bundler(bundler_version) 78 | if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0") 79 | bundler_version = "< 2" 80 | end 81 | gem_error = activation_error_handling do 82 | gem "bundler", bundler_version 83 | end 84 | return if gem_error.nil? 85 | require_error = activation_error_handling do 86 | require "bundler/version" 87 | end 88 | return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 89 | warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`" 90 | exit 42 91 | end 92 | 93 | def activation_error_handling 94 | yield 95 | nil 96 | rescue StandardError, LoadError => e 97 | e 98 | end 99 | end 100 | 101 | m.load_bundler! 102 | 103 | if m.invoked_as_script? 104 | load Gem.bin_path("bundler", "bundle") 105 | end 106 | -------------------------------------------------------------------------------- /bin/bundle-audit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle-audit' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("bundler-audit", "bundle-audit") 30 | -------------------------------------------------------------------------------- /bin/bundler: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | # 4 | # This file was generated by Bundler. 5 | # 6 | # The application 'bundler' is installed as part of a gem, and 7 | # this file is here to facilitate running it. 8 | # 9 | 10 | require "pathname" 11 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 12 | Pathname.new(__FILE__).realpath) 13 | 14 | require "rubygems" 15 | require "bundler/setup" 16 | 17 | load Gem.bin_path("bundler", "bundler") 18 | -------------------------------------------------------------------------------- /bin/bundler-audit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundler-audit' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("bundler-audit", "bundler-audit") 30 | -------------------------------------------------------------------------------- /bin/byebug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'byebug' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("byebug", "byebug") 30 | -------------------------------------------------------------------------------- /bin/chromedriver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'chromedriver' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("chromedriver-helper", "chromedriver") 30 | -------------------------------------------------------------------------------- /bin/chromedriver-update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'chromedriver-update' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("chromedriver-helper", "chromedriver-update") 30 | -------------------------------------------------------------------------------- /bin/coderay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'coderay' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("coderay", "coderay") 30 | -------------------------------------------------------------------------------- /bin/configure: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function printSeparator() { 4 | printf "\n*************\n\n"; 5 | } 6 | 7 | read -p "Do you want to keep tracking the template via git? y/n: " -n 1 -r 8 | echo 9 | if [[ $REPLY =~ ^[Yy]$ ]] ; then 10 | echo "Renaming remote from 'origin' to 'template'" 11 | git remote rename origin template 12 | else 13 | echo "Removing remote 'origin'" 14 | git remote remove origin 15 | fi 16 | 17 | printSeparator 18 | 19 | echo "Installing gems and JS dependencies" 20 | bundle install 21 | echo 22 | yarn install 23 | 24 | printSeparator 25 | 26 | read -p "Will you be using figaro for this project? y/n: " -n 1 -r 27 | echo 28 | if [[ $REPLY =~ ^[Yy]$ ]] ; then 29 | echo "Copying 'config/application.yml.example' to 'config/application.yml'" 30 | cp config/application.yml.example config/application.yml 31 | fi 32 | 33 | printSeparator 34 | 35 | printf "Please update the following locations:\n\n" 36 | bundle exec rake notes 37 | echo "./package.json:" 38 | echo " * [ 2] Update name attribute" 39 | 40 | -------------------------------------------------------------------------------- /bin/figaro: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'figaro' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("figaro", "figaro") 30 | -------------------------------------------------------------------------------- /bin/foreman: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'foreman' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("foreman", "foreman") 30 | -------------------------------------------------------------------------------- /bin/htmldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'htmldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("diff-lcs", "htmldiff") 30 | -------------------------------------------------------------------------------- /bin/launchy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'launchy' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("launchy", "launchy") 30 | -------------------------------------------------------------------------------- /bin/ldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("diff-lcs", "ldiff") 30 | -------------------------------------------------------------------------------- /bin/listen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'listen' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("listen", "listen") 30 | -------------------------------------------------------------------------------- /bin/local_server: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | foreman start -f Procfile.dev 3 | -------------------------------------------------------------------------------- /bin/mongrel_rpm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'mongrel_rpm' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("newrelic_rpm", "mongrel_rpm") 30 | -------------------------------------------------------------------------------- /bin/newrelic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'newrelic' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("newrelic_rpm", "newrelic") 30 | -------------------------------------------------------------------------------- /bin/newrelic_cmd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'newrelic_cmd' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("newrelic_rpm", "newrelic_cmd") 30 | -------------------------------------------------------------------------------- /bin/nokogiri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nokogiri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("nokogiri", "nokogiri") 30 | -------------------------------------------------------------------------------- /bin/nrdebug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nrdebug' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("newrelic_rpm", "nrdebug") 30 | -------------------------------------------------------------------------------- /bin/nullalign: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nullalign' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("nullalign", "nullalign") 30 | -------------------------------------------------------------------------------- /bin/pry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pry' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("pry", "pry") 30 | -------------------------------------------------------------------------------- /bin/puma: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'puma' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("puma", "puma") 30 | -------------------------------------------------------------------------------- /bin/pumactl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pumactl' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("puma", "pumactl") 30 | -------------------------------------------------------------------------------- /bin/rackup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rackup' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rack", "rackup") 30 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rspec-core", "rspec") 30 | -------------------------------------------------------------------------------- /bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rubocop' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("rubocop", "rubocop") 30 | -------------------------------------------------------------------------------- /bin/ruby-parse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-parse' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("parser", "ruby-parse") 30 | -------------------------------------------------------------------------------- /bin/ruby-prof: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-prof' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("ruby-prof", "ruby-prof") 30 | -------------------------------------------------------------------------------- /bin/ruby-prof-check-trace: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-prof-check-trace' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("ruby-prof", "ruby-prof-check-trace") 30 | -------------------------------------------------------------------------------- /bin/ruby-rewrite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-rewrite' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("parser", "ruby-rewrite") 30 | -------------------------------------------------------------------------------- /bin/safe_yaml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'safe_yaml' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("safe_yaml", "safe_yaml") 30 | -------------------------------------------------------------------------------- /bin/sass: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sass' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sass", "sass") 30 | -------------------------------------------------------------------------------- /bin/sass-convert: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sass-convert' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sass", "sass-convert") 30 | -------------------------------------------------------------------------------- /bin/scss: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'scss' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sass", "scss") 30 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to setup or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at anytime and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies 21 | # system('bin/yarn') 22 | 23 | # puts "\n== Copying sample files ==" 24 | # unless File.exist?('config/database.yml') 25 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 26 | # end 27 | 28 | puts "\n== Preparing database ==" 29 | system! 'bin/rails db:prepare' 30 | 31 | puts "\n== Removing old logs and tempfiles ==" 32 | system! 'bin/rails log:clear tmp:clear' 33 | 34 | puts "\n== Restarting application server ==" 35 | system! 'bin/rails restart' 36 | end 37 | -------------------------------------------------------------------------------- /bin/sidekiq: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sidekiq' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sidekiq", "sidekiq") 30 | -------------------------------------------------------------------------------- /bin/sidekiqctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sidekiqctl' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sidekiq", "sidekiqctl") 30 | -------------------------------------------------------------------------------- /bin/sprockets: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sprockets' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("sprockets", "sprockets") 30 | -------------------------------------------------------------------------------- /bin/thor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'thor' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("thor", "thor") 30 | -------------------------------------------------------------------------------- /bin/tilt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'tilt' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("tilt", "tilt") 30 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a way to update your development environment automatically. 14 | # Add necessary update steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies if using Yarn 21 | # system('bin/yarn') 22 | 23 | puts "\n== Updating database ==" 24 | system! 'bin/rails db:migrate' 25 | 26 | puts "\n== Removing old logs and tempfiles ==" 27 | system! 'bin/rails log:clear tmp:clear' 28 | 29 | puts "\n== Restarting application server ==" 30 | system! 'bin/rails restart' 31 | end 32 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "rubygems" 11 | require "bundler/setup" 12 | 13 | require "webpacker" 14 | require "webpacker/webpack_runner" 15 | 16 | APP_ROOT = File.expand_path("..", __dir__) 17 | Dir.chdir(APP_ROOT) do 18 | Webpacker::WebpackRunner.run(ARGV) 19 | end 20 | -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "rubygems" 11 | require "bundler/setup" 12 | 13 | require "webpacker" 14 | require "webpacker/dev_server_runner" 15 | 16 | APP_ROOT = File.expand_path("..", __dir__) 17 | Dir.chdir(APP_ROOT) do 18 | Webpacker::DevServerRunner.run(ARGV) 19 | end 20 | -------------------------------------------------------------------------------- /bin/yard: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yard' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yard") 30 | -------------------------------------------------------------------------------- /bin/yardoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yardoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yardoc") 30 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /bin/yri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'yri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path("../bundle", __FILE__) 16 | 17 | if File.file?(bundle_binstub) 18 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require "rubygems" 27 | require "bundler/setup" 28 | 29 | load Gem.bin_path("yard", "yri") 30 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require_relative 'config/environment' 6 | 7 | run Rails.application 8 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'boot' 4 | 5 | require 'rails/all' 6 | 7 | require_relative '../lib/rack/reject_trace' 8 | 9 | # Require the gems listed in Gemfile, including any gems 10 | # you've limited to :test, :development, or :production. 11 | Bundler.require(*Rails.groups) 12 | 13 | # TODO: Change module name to the actual project name 14 | module RailsNew 15 | class Application < Rails::Application 16 | ENV_TRUTHY = %w[enabled true t 1].freeze 17 | 18 | # Initialize configuration defaults for originally generated Rails version. 19 | config.load_defaults 7.0 20 | 21 | # Settings in config/environments/* take precedence over those specified here. 22 | # Application configuration can go into files in config/initializers 23 | # -- all .rb files in that directory are automatically loaded after loading 24 | # the framework and any gems in your application. 25 | 26 | # Use Sidekiq as ActiveJob backend 27 | config.active_job.queue_adapter = :sidekiq 28 | 29 | # React-Rails config 30 | config.react.camelize_props = true 31 | 32 | # Configure generators, see: http://guides.rubyonrails.org/generators.html 33 | config.generators do |g| 34 | # Create appropriate tests in spec/ not test/ 35 | g.test_framework :rspec, fixture: true 36 | g.fixture_replacement :factory_bot, dir: 'spec/factories' 37 | 38 | # Don't generate helpers, JS, CSS or view specs for controllers 39 | # See: http://guides.rubyonrails.org/generators.html 40 | g.helper false 41 | g.javascripts false 42 | g.stylesheets false 43 | g.view_specs false 44 | 45 | if ENV['BLOCK_HTTP_TRACE'].in?(ENV_TRUTHY) 46 | config.middleware.use Rack::RejectTrace 47 | end 48 | 49 | if ENV['RAILS_LOG_TO_STDOUT'].in?(ENV_TRUTHY) 50 | logger = ActiveSupport::Logger.new($stdout) 51 | logger.formatter = config.log_formatter 52 | config.logger = ActiveSupport::TaggedLogging.new(logger) 53 | end 54 | end 55 | 56 | config.add_autoload_paths_to_load_path = false 57 | 58 | # Warn if we inadvertently attempt to pull more records into memory 59 | # than the default `find_each` batch size of 1000: 60 | config.active_record.warn_on_records_fetched_greater_than = 1001 61 | 62 | # Opt out of Google's FLoC. 63 | # See https://andycroll.com/ruby/opt-out-of-google-floc-tracking-in-rails/ 64 | config.action_dispatch.default_headers['Permissions-Policy'] = 65 | 'interest-cohort=()' 66 | 67 | config.action_mailer.deliver_later_queue_name = :mailers 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /config/application.yml.example: -------------------------------------------------------------------------------- 1 | # NOTE: This sample file is **NOT** comprehensive. If there are well-defined 2 | # and necessary environment variables that are both universally relevant and 3 | # publicly accessible/shareable they can be included here, otherwise see the 4 | # README#environment-variables section. 5 | DATABASE_URL: 'postgres://localhost:5432/rails_new_development' 6 | HOST: 'http://localhost:3000' 7 | RAILS_MAX_THREADS: '5' 8 | WEB_CONCURRENCY: '1' 9 | REDIS_URL: 'redis://localhost:6379' 10 | RAILS_SYSTEM_TESTING_SCREENSHOT: 'inline' 11 | 12 | # When using Docker use this instead: 13 | # DATABASE_URL: 'postgres://postgres@postgres:5432/rails_new_development' 14 | # RAILS_LOG_TO_STDOUT: 'true' 15 | # REDIS_URL: 'redis://redis:6379' 16 | 17 | test: 18 | DATABASE_URL: 'postgres://localhost:5432/rails_new_test' 19 | # When using Docker use this instead: 20 | # DATABASE_URL: 'postgres://postgres@postgres:5432/rails_new_test' 21 | # RAILS_LOG_TO_STDOUT: 'false' 22 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 4 | 5 | require 'bundler/setup' # Set up gems listed in the Gemfile. 6 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 7 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | # TODO: Change channel prefix 11 | channel_prefix: rails_new_production 12 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 9.1 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On OS X with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On OS X with MacPorts: 8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config 9 | # On Windows: 10 | # gem install pg 11 | # Choose the win32 build. 12 | # Install PostgreSQL and put its /bin directory on your path. 13 | # 14 | # Configure Using Gemfile 15 | # gem 'pg' 16 | # 17 | default: &default 18 | adapter: postgresql 19 | encoding: unicode 20 | # For details on connection pooling, see Rails configuration guide 21 | # http://guides.rubyonrails.org/configuring.html#database-pooling 22 | # TODO: Configure DATABASE_URL in config/application.yml 23 | url: <%= ENV["DATABASE_URL"] %> 24 | # NOTE: In some cases we'll use RAILS_MAX_THREADS as the sidekiq concurrency. 25 | # Indeed, sidekiq will use this value internally by default if it is set and 26 | # concurrency isn't explicitly configured. However, this means the worker 27 | # thread count is tied to the web (Puma) thread count, which makes less sense 28 | # as each server type is optimized for performance. So to accommodate more 29 | # advanced configurations we will allow for the pool size to be set at a value 30 | # specific to the server type (i.e. DB_POOL), but fall back to 31 | # RAILS_MAX_THREADS which will be an appropriate default pool size for both 32 | # server types if concurrency doesn't differ between them. 33 | # 34 | # We'll also want to add a connection "buffer" (increase the pool size by a 35 | # few connections) just in case other libraries eagerly grab connections 36 | # from the pool before sidekiq spawns the workers, leading to connection 37 | # timeouts from sidekiq. See the comment from Andrew Babichev here: 38 | # https://gist.github.com/nateberkopec/56936904705da5a1fa8e6f74cb08c012 39 | pool: <%= (ENV['DB_POOL'] || ENV['RAILS_MAX_THREADS'] || 5).to_i + 5 %> 40 | 41 | development: 42 | <<: *default 43 | # The specified database role being used to connect to postgres. 44 | # To create additional roles in postgres see `$ createuser --help`. 45 | # When left blank, postgres will use the default role. This is 46 | # the same name as the operating system user that initialized the database. 47 | #username: rails_new 48 | 49 | # The password associated with the postgres role (username). 50 | #password: 51 | 52 | # Connect on a TCP socket. Omitted by default since the client uses a 53 | # domain socket that doesn't need configuration. Windows does not have 54 | # domain sockets, so uncomment these lines. 55 | #host: localhost 56 | 57 | # The TCP port the server listens on. Defaults to 5432. 58 | # If your server runs on a different port number, change accordingly. 59 | #port: 5432 60 | 61 | # Schema search path. The server defaults to $user,public 62 | #schema_search_path: myapp,sharedapp,public 63 | 64 | # Minimum log levels, in increasing order: 65 | # debug5, debug4, debug3, debug2, debug1, 66 | # log, notice, warning, error, fatal, and panic 67 | # Defaults to warning. 68 | #min_messages: notice 69 | 70 | # Warning: The database defined as "test" will be erased and 71 | # re-generated from your development database when you run "rake". 72 | # Do not set this db to the same as development or production. 73 | test: 74 | <<: *default 75 | 76 | # As with config/secrets.yml, you never want to store sensitive information, 77 | # like your database password, in your source code. If your source code is 78 | # ever seen by anyone, they now have access to your database. 79 | # 80 | # Instead, provide the password as a unix environment variable when you boot 81 | # the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database 82 | # for a full rundown on how to provide these environment variables in a 83 | # production deployment. 84 | # 85 | # On Heroku and other platform providers, you may have a full connection URL 86 | # available as an environment variable. For example: 87 | # 88 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" 89 | # 90 | # You can use this database configuration with: 91 | # 92 | # production: 93 | # url: <%= ENV['DATABASE_URL'] %> 94 | # 95 | production: 96 | <<: *default 97 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative 'application' 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'active_support/core_ext/integer/time' 4 | 5 | Rails.application.configure do 6 | # Settings specified here will take precedence over those in config/application.rb. 7 | 8 | # In the development environment your application's code is reloaded on 9 | # every request. This slows down response time but is perfect for development 10 | # since you don't have to restart the web server when you make code changes. 11 | config.cache_classes = false 12 | 13 | # Do not eager load code on boot. 14 | config.eager_load = false 15 | 16 | # Show full error reports. 17 | config.consider_all_requests_local = true 18 | 19 | # Enable server timing 20 | config.server_timing = true 21 | 22 | # Enable/disable caching. By default caching is disabled. 23 | # Run rails dev:cache to toggle caching. 24 | if Rails.root.join('tmp/caching-dev.txt').exist? 25 | config.action_controller.perform_caching = true 26 | config.action_controller.enable_fragment_cache_logging = true 27 | 28 | config.cache_store = :memory_store 29 | config.public_file_server.headers = { 30 | 'Cache-Control' => "public, max-age=#{2.days.to_i}", 31 | } 32 | else 33 | config.action_controller.perform_caching = false 34 | 35 | config.cache_store = :null_store 36 | end 37 | 38 | # Store uploaded files on the local file system (see config/storage.yml for options) 39 | config.active_storage.service = :local 40 | 41 | # In production, :host should be set to the actual host of your application. 42 | config.action_mailer.default_url_options = { 43 | host: 'localhost', 44 | port: ENV.fetch('PORT', 3000), 45 | } 46 | 47 | # Review emails in the browser instead of the logs 48 | config.action_mailer.delivery_method = :letter_opener 49 | 50 | # Don't care if the mailer can't send. 51 | config.action_mailer.raise_delivery_errors = false 52 | 53 | config.action_mailer.perform_caching = false 54 | 55 | # Print deprecation notices to the Rails logger. 56 | config.active_support.deprecation = :log 57 | 58 | # Raise exceptions for disallowed deprecations. 59 | config.active_support.disallowed_deprecation = :raise 60 | 61 | # Tell Active Support which deprecation messages to disallow. 62 | config.active_support.disallowed_deprecation_warnings = [] 63 | 64 | # Raise an error on page load if there are pending migrations. 65 | config.active_record.migration_error = :page_load 66 | 67 | # Highlight code that triggered database queries in logs. 68 | config.active_record.verbose_query_logs = true 69 | 70 | # Suppress logger output for asset requests. 71 | config.assets.quiet = true 72 | 73 | # Raises error for missing translations 74 | # config.action_view.raise_on_missing_translations = true 75 | 76 | # Use an evented file watcher to asynchronously detect changes in source code, 77 | # routes, locales, etc. This feature depends on the listen gem. 78 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker 79 | 80 | # Bullet, https://github.com/flyerhzm/bullet#configuration 81 | config.after_initialize do 82 | Bullet.enable = false 83 | Bullet.rails_logger = true 84 | Bullet.add_footer = true 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'active_support/core_ext/integer/time' 4 | 5 | # The test environment is used exclusively to run your application's 6 | # test suite. You never need to work with it otherwise. Remember that 7 | # your test database is "scratch space" for the test suite and is wiped 8 | # and recreated between test runs. Don't rely on the data there! 9 | 10 | Rails.application.configure do 11 | # Settings specified here will take precedence over those in config/application.rb. 12 | 13 | config.cache_classes = false 14 | 15 | # Eager loading loads your whole application. When running a single test locally, 16 | # this probably isn't necessary. It's a good idea to do in a continuous integration 17 | # system, or in some way before deploying your code. 18 | config.eager_load = ENV['CI'].present? 19 | 20 | # Configure public file server for tests with Cache-Control for performance. 21 | config.public_file_server.enabled = true 22 | config.public_file_server.headers = { 23 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}", 24 | } 25 | 26 | # Show full error reports and disable caching. 27 | config.consider_all_requests_local = true 28 | config.action_controller.perform_caching = false 29 | config.cache_store = :null_store 30 | 31 | # Raise exceptions instead of rendering exception templates. 32 | config.action_dispatch.show_exceptions = false 33 | 34 | # Disable request forgery protection in test environment. 35 | config.action_controller.allow_forgery_protection = false 36 | 37 | # Store uploaded files on the local file system in a temporary directory. 38 | config.active_storage.service = :test 39 | 40 | config.action_mailer.perform_caching = false 41 | 42 | # Tell Action Mailer not to deliver emails to the real world. 43 | # The :test delivery method accumulates sent emails in the 44 | # ActionMailer::Base.deliveries array. 45 | config.action_mailer.delivery_method = :test 46 | 47 | # Emails generated in the test suite that include urls need a host value. 48 | config.action_mailer.default_url_options = { 49 | host: 'localhost', 50 | port: ENV.fetch('PORT', 3000), 51 | } 52 | 53 | # Print deprecation notices to the stderr. 54 | config.active_support.deprecation = :stderr 55 | 56 | # Raise exceptions for disallowed deprecations. 57 | config.active_support.disallowed_deprecation = :raise 58 | 59 | # Tell Active Support which deprecation messages to disallow. 60 | config.active_support.disallowed_deprecation_warnings = [] 61 | 62 | # See: https://github.com/flyerhzm/bullet#run-in-tests 63 | config.after_initialize do 64 | Bullet.enable = false 65 | 66 | # Raises error if n+1 query occurs. 67 | Bullet.raise = true 68 | end 69 | 70 | # Set random value for CircleCI and friends 71 | config.secret_key_base = SecureRandom.hex(64) 72 | end 73 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # ActiveSupport::Reloader.to_prepare do 6 | # ApplicationController.renderer.defaults.merge!( 7 | # http_host: 'example.org', 8 | # https: false 9 | # ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = '1.0' 7 | 8 | # Add additional assets to the asset load path. 9 | # Rails.application.config.assets.paths << Emoji.images_path 10 | # Add Yarn node_modules folder to the asset load path. 11 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 12 | 13 | # Precompile additional assets. 14 | # application.js, application.css, and all non-JS/CSS in the app/assets 15 | # folder are already added. 16 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 17 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 6 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 7 | 8 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 9 | # Rails.backtrace_cleaner.remove_silencers! 10 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Define an application-wide content security policy 6 | # For further information see the following documentation 7 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 8 | 9 | # Rails.application.configure do 10 | # config.content_security_policy do |policy| 11 | # policy.default_src :self, :https 12 | # policy.font_src :self, :https, :data 13 | # policy.img_src :self, :https, :data 14 | # policy.object_src :none 15 | # policy.script_src :self, :https 16 | # policy.style_src :self, :https 17 | # # Specify URI for violation reports 18 | # # policy.report_uri "/csp-violation-report-endpoint" 19 | # end 20 | # 21 | # # Generate session nonces for permitted importmap and inline scripts 22 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 23 | # config.content_security_policy_nonce_directives = %w(script-src) 24 | # 25 | # # Report CSP violations to a specified URI. See: 26 | # # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 27 | # # config.content_security_policy_report_only = true 28 | # end 29 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Specify a serializer for the signed and encrypted cookie jars. 6 | # Valid options are :json, :marshal, and :hybrid. 7 | Rails.application.config.action_dispatch.cookies_serializer = :json 8 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure parameters to be filtered from the log file. Use this to limit dissemination of 6 | # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported 7 | # notations and behaviors. 8 | Rails.application.config.filter_parameters += %i[ 9 | passw secret token _key crypt salt certificate otp ssn 10 | ] 11 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new inflection rules using the following format. Inflections 6 | # are locale specific, and you may define rules for as many different 7 | # locales as you wish. All of these examples are active by default: 8 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 9 | # inflect.plural /^(ox)$/i, '\1en' 10 | # inflect.singular /^(ox)en/i, '\1' 11 | # inflect.irregular 'person', 'people' 12 | # inflect.uncountable %w( fish sheep ) 13 | # end 14 | 15 | # These inflection rules are supported but not enabled by default: 16 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 17 | # inflect.acronym 'RESTful' 18 | # end 19 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new mime types for use in respond_to blocks: 6 | # Mime::Type.register "text/richtext", :rtf 7 | -------------------------------------------------------------------------------- /config/initializers/new_framework_defaults_5_1.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | # 5 | # This file contains migration options to ease your Rails 5.1 upgrade. 6 | # 7 | # Once upgraded flip defaults one by one to migrate to the new default. 8 | # 9 | # Read the Guide for Upgrading Ruby on Rails for more info on each option. 10 | 11 | # Make `form_with` generate non-remote forms. 12 | # Rails.application.config.action_view.form_with_generates_remote_forms = false 13 | 14 | # Unknown asset fallback will return the path passed in when the given 15 | # asset is not present in the asset pipeline. 16 | # Rails.application.config.assets.unknown_asset_fallback = false 17 | -------------------------------------------------------------------------------- /config/initializers/new_framework_defaults_5_2.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | # 5 | # This file contains migration options to ease your Rails 5.2 upgrade. 6 | # 7 | # Once upgraded flip defaults one by one to migrate to the new default. 8 | # 9 | # Read the Guide for Upgrading Ruby on Rails for more info on each option. 10 | 11 | # Make Active Record use stable #cache_key alongside new #cache_version method. 12 | # This is needed for recyclable cache keys. 13 | # Rails.application.config.active_record.cache_versioning = true 14 | 15 | # Use AES-256-GCM authenticated encryption for encrypted cookies. 16 | # Also, embed cookie expiry in signed or encrypted cookies for increased security. 17 | # 18 | # This option is not backwards compatible with earlier Rails versions. 19 | # It's best enabled when your entire app is migrated and stable on 5.2. 20 | # 21 | # Existing cookies will be converted on read then written with the new scheme. 22 | # Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true 23 | 24 | # Use AES-256-GCM authenticated encryption as default cipher for encrypting messages 25 | # instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. 26 | # Rails.application.config.active_support.use_authenticated_message_encryption = true 27 | 28 | # Add default protection from forgery to ActionController::Base instead of in 29 | # ApplicationController. 30 | # Rails.application.config.action_controller.default_protect_from_forgery = true 31 | 32 | # Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and 33 | # 'f' after migrating old data. 34 | # Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true 35 | 36 | # Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. 37 | # Rails.application.config.active_support.use_sha1_digests = true 38 | 39 | # Make `form_with` generate id attributes for any generated HTML tags. 40 | # Rails.application.config.action_view.form_with_generates_ids = true 41 | -------------------------------------------------------------------------------- /config/initializers/new_framework_defaults_6_0.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | # 5 | # This file contains migration options to ease your Rails 6.0 upgrade. 6 | # 7 | # Once upgraded flip defaults one by one to migrate to the new default. 8 | # 9 | # Read the Guide for Upgrading Ruby on Rails for more info on each option. 10 | 11 | # Don't force requests from old versions of IE to be UTF-8 encoded. 12 | # Rails.application.config.action_view.default_enforce_utf8 = false 13 | 14 | # Embed purpose and expiry metadata inside signed and encrypted 15 | # cookies for increased security. 16 | # 17 | # This option is not backwards compatible with earlier Rails versions. 18 | # It's best enabled when your entire app is migrated and stable on 6.0. 19 | # Rails.application.config.action_dispatch.use_cookies_with_metadata = true 20 | 21 | # Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification. 22 | # Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false 23 | 24 | # Return false instead of self when enqueuing is aborted from a callback. 25 | # Rails.application.config.active_job.return_false_on_aborted_enqueue = true 26 | 27 | # Send Active Storage analysis and purge jobs to dedicated queues. 28 | # Rails.application.config.active_storage.queues.analysis = :active_storage_analysis 29 | # Rails.application.config.active_storage.queues.purge = :active_storage_purge 30 | 31 | # When assigning to a collection of attachments declared via `has_many_attached`, replace existing 32 | # attachments instead of appending. Use #attach to add new attachments without replacing existing ones. 33 | # Rails.application.config.active_storage.replace_on_assign_to_many = true 34 | 35 | # Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail. 36 | # 37 | # The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob), 38 | # will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions. 39 | # If you send mail in the background, job workers need to have a copy of 40 | # MailDeliveryJob to ensure all delivery jobs are processed properly. 41 | # Make sure your entire app is migrated and stable on 6.0 before using this setting. 42 | # Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" 43 | 44 | # Enable the same cache key to be reused when the object being cached of type 45 | # `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count) 46 | # of the relation's cache key into the cache version to support recycling cache key. 47 | # Rails.application.config.active_record.collection_cache_versioning = true 48 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Define an application-wide HTTP permissions policy. For further 3 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 4 | # 5 | # Rails.application.config.permissions_policy do |f| 6 | # f.camera :none 7 | # f.gyroscope :none 8 | # f.microphone :none 9 | # f.usb :none 10 | # f.fullscreen :self 11 | # f.payment :self, "https://secure.example.com" 12 | # end 13 | -------------------------------------------------------------------------------- /config/initializers/rack_mini_profiler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if Rails.env.development? 4 | require 'rack-mini-profiler' 5 | 6 | # initialization is skipped so trigger it 7 | Rack::MiniProfilerRails.initialize!(Rails.application) 8 | Rack::MiniProfiler.config.position = 'bottom-left' 9 | end 10 | -------------------------------------------------------------------------------- /config/initializers/secure_headers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if Rails.env.production? 4 | require 'secure_headers' 5 | 6 | # See: https://github.com/twitter/secureheaders 7 | SecureHeaders::Configuration.default 8 | end 9 | -------------------------------------------------------------------------------- /config/initializers/sentry.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Sentry.init do |config| 4 | config.dsn = ENV.fetch('SENTRY_DSN_BACKEND', nil) 5 | config.async = lambda { |event, hint| 6 | Sentry::SendEventJob.perform_later(event, hint) 7 | } 8 | end 9 | -------------------------------------------------------------------------------- /config/initializers/sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # See https://github.com/jollygoodcode/jollygoodcode.github.io/issues/12 4 | # and https://bryanrite.com/heroku-puma-redis-sidekiq-and-connection-limits/ 5 | # 6 | # Client Size = Puma Workers * (Puma Threads / 2) * Heroku Web Dynos 7 | # 8 | # Server Size = (Redis Connection Limit - Client Size - 2) / Heroku Worker Dynos 9 | # Server Size is set in sidekiq.yml in concurrency setting. 10 | # Server size is concurrency + 2. 11 | 12 | puma_workers = ENV.fetch('WEB_CONCURRENCY', 1).to_i 13 | puma_threads = ENV.fetch('RAILS_MAX_THREADS', 5).to_i 14 | 15 | # If we only have one puma thread, the division could end up being 0 16 | effective_threads = [(puma_threads / 2), 1].max 17 | 18 | # configure this to reflect your Heroku setup 19 | web_dynos = 1 20 | 21 | client_size = puma_workers * effective_threads * web_dynos 22 | 23 | Sidekiq.configure_client do |config| 24 | config.redis = { size: client_size, url: ENV.fetch('REDIS_URL', nil) } 25 | end 26 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # This file contains settings for ActionController::ParamsWrapper which 6 | # is enabled by default. 7 | 8 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 9 | ActiveSupport.on_load(:action_controller) do 10 | wrap_parameters format: [:json] 11 | end 12 | 13 | # To enable root element in JSON for ActiveRecord objects. 14 | # ActiveSupport.on_load(:active_record) do 15 | # self.include_root_in_json = true 16 | # end 17 | -------------------------------------------------------------------------------- /config/locales/devise.en.yml: -------------------------------------------------------------------------------- 1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n 2 | 3 | en: 4 | devise: 5 | confirmations: 6 | confirmed: "Your email address has been successfully confirmed." 7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." 8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." 9 | failure: 10 | already_authenticated: "You are already signed in." 11 | inactive: "Your account is not activated yet." 12 | invalid: "Invalid %{authentication_keys} or password." 13 | locked: "Your account is locked." 14 | last_attempt: "You have one more attempt before your account is locked." 15 | not_found_in_database: "Invalid %{authentication_keys} or password." 16 | timeout: "Your session expired. Please sign in again to continue." 17 | unauthenticated: "You need to sign in or sign up before continuing." 18 | unconfirmed: "You have to confirm your email address before continuing." 19 | mailer: 20 | confirmation_instructions: 21 | subject: "Confirmation instructions" 22 | reset_password_instructions: 23 | subject: "Reset password instructions" 24 | unlock_instructions: 25 | subject: "Unlock instructions" 26 | email_changed: 27 | subject: "Email Changed" 28 | password_change: 29 | subject: "Password Changed" 30 | omniauth_callbacks: 31 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"." 32 | success: "Successfully authenticated from %{kind} account." 33 | passwords: 34 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." 35 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." 36 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." 37 | updated: "Your password has been changed successfully. You are now signed in." 38 | updated_not_active: "Your password has been changed successfully." 39 | registrations: 40 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." 41 | signed_up: "Welcome! You have signed up successfully." 42 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." 43 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." 44 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." 45 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." 46 | updated: "Your account has been updated successfully." 47 | sessions: 48 | signed_in: "Signed in successfully." 49 | signed_out: "Signed out successfully." 50 | already_signed_out: "Signed out successfully." 51 | unlocks: 52 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." 53 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." 54 | unlocked: "Your account has been unlocked successfully. Please sign in to continue." 55 | errors: 56 | messages: 57 | already_confirmed: "was already confirmed, please try signing in" 58 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" 59 | expired: "has expired, please request a new one" 60 | not_found: "not found" 61 | not_locked: "was not locked" 62 | not_saved: 63 | one: "1 error prohibited this %{resource} from being saved:" 64 | other: "%{count} errors prohibited this %{resource} from being saved:" 65 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at http://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | app: 34 | authenticity_token_expired: 35 | 'Your browser window has been idle for too long. As a security measure you 36 | will need to resubmit your request.' 37 | default_title: 'Rails New' 38 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | require 'barnes' 2 | 3 | # Puma can serve each request in a thread from an internal thread pool. 4 | # The `threads` method setting takes two numbers: a minimum and maximum. 5 | # Any libraries that use thread pools should be configured to match 6 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 7 | # and maximum; this matches the default thread size of Active Record. 8 | # 9 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 10 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 11 | threads min_threads_count, max_threads_count 12 | 13 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 14 | # 15 | port ENV.fetch("PORT") { 3000 } 16 | 17 | # Specifies the `environment` that Puma will run in. 18 | # 19 | environment ENV.fetch("RAILS_ENV") { "development" } 20 | 21 | # Specifies the `pidfile` that Puma will use. 22 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 23 | 24 | # Specifies the number of `workers` to boot in clustered mode. 25 | # Workers are forked web server processes. If using threads and workers together 26 | # the concurrency of the application would be max `threads` * `workers`. 27 | # Workers do not work on JRuby or Windows (both of which do not support 28 | # processes). 29 | # 30 | workers ENV.fetch("WEB_CONCURRENCY") { 1 } 31 | 32 | # Use the `preload_app!` method when specifying a `workers` number. 33 | # This directive tells Puma to first boot the application and load code 34 | # before forking the application. This takes advantage of Copy On Write 35 | # process behavior so workers use less memory. 36 | # 37 | if ENV.fetch('WEB_CONCURRENCY', 1) 38 | preload_app! 39 | 40 | before_fork do 41 | Barnes.start 42 | end 43 | end 44 | 45 | # Allow puma to be restarted by `rails restart` command. 46 | plugin :tmp_restart 47 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Rails.application.routes.draw do 4 | devise_for :accounts 5 | 6 | # TODO: Add root route as needed/necessary 7 | # unauthenticated :user do 8 | # root to: 'static_pages#landing' 9 | # end 10 | end 11 | -------------------------------------------------------------------------------- /config/sidekiq.yml: -------------------------------------------------------------------------------- 1 | # Taken from https://github.com/mperham/sidekiq/blob/master/examples/config.yml 2 | # Sample configuration file for Sidekiq. 3 | # Options here can still be overridden by cmd line args. 4 | # Place this file at config/sidekiq.yml and Sidekiq will 5 | # pick it up automatically. 6 | --- 7 | :verbose: false 8 | 9 | # Set timeout to 8 on Heroku, longer if you manage your own systems. 10 | :timeout: 8 11 | 12 | # Sidekiq will run this file through ERB when reading it so you can 13 | # even put in dynamic logic, like a host-specific queue. 14 | # http://www.mikeperham.com/2013/11/13/advanced-sidekiq-host-specific-queues/ 15 | :queues: 16 | - critical 17 | - default 18 | - low 19 | - mailers 20 | 21 | # You can override concurrency based on environment. It is common practice 22 | # to let concurrency be dictated by RAILS_MAX_THREADS, see details here: 23 | # https://gist.github.com/nateberkopec/2d1fcf77dc61e747438252e3895badf0 24 | # 25 | # That said, you may not want your worker concurrency and web thread 26 | # count tied together, so you can optionally set a WORKER_CONCURRENCY 27 | # value: 28 | :concurrency: <%= ENV['WORKER_CONCURRENCY'] || ENV['RAILS_MAX_THREADS'] || 5 %> 29 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: | 13 | # <%= ENV.fetch("AWS_KEY_ID") { Rails.application.credentials.dig(:aws, :access_key_id) } %> 14 | # secret_access_key: | 15 | # <%= ENV.fetch("AWS_SECRET_ACCESS_KEY") { Rails.application.credentials.dig(:aws, :secret_access_key) } %> 16 | # region: us-east-1 17 | # bucket: your_own_bucket 18 | 19 | # Remember not to checkin your GCS keyfile to a repository 20 | # google: 21 | # service: GCS 22 | # project: your_project 23 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 24 | # bucket: your_own_bucket 25 | 26 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 27 | # microsoft: 28 | # service: AzureStorage 29 | # storage_account_name: your_account_name 30 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 31 | # container: your_container_name 32 | 33 | # mirror: 34 | # service: Mirror 35 | # primary: local 36 | # mirrors: [ amazon, google, microsoft ] 37 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || "development" 2 | 3 | const environment = require("./environment"); 4 | 5 | // This is necessary to fix runtime errors when hot-loading mjs modules 6 | const nodeModulesLoader = environment.loaders.get("nodeModules"); 7 | nodeModulesLoader.type = "javascript/auto"; 8 | 9 | module.exports = environment.toWebpackConfig(); 10 | -------------------------------------------------------------------------------- /config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require("@rails/webpacker"); 2 | const typescript = require("./loaders/typescript"); 3 | 4 | environment.loaders.prepend("typescript", typescript); 5 | module.exports = environment; 6 | -------------------------------------------------------------------------------- /config/webpack/loaders/typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test: /\.(ts|tsx)?(\.erb)?$/, 3 | use: [ 4 | { 5 | loader: "babel-loader" 6 | } 7 | ] 8 | }; 9 | -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || "production" 2 | 3 | const environment = require("./environment"); 4 | 5 | // Do not bundle-split in development to make HMR possible 6 | environment.splitChunks(config => 7 | Object.assign({}, config, { 8 | optimization: { 9 | splitChunks: { 10 | cacheGroups: { 11 | vendor: { 12 | test: /node_modules/, 13 | chunks: "all", 14 | name: "vendor", 15 | enforce: true 16 | } 17 | } 18 | } 19 | } 20 | }) 21 | ); 22 | 23 | module.exports = environment.toWebpackConfig(); 24 | -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || "development" 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /config/webpacker.yml: -------------------------------------------------------------------------------- 1 | # Note: You must restart bin/webpack-dev-server for changes to take effect 2 | 3 | default: &default 4 | source_path: app/javascript 5 | source_entry_path: packs 6 | public_root_path: public 7 | public_output_path: packs 8 | cache_path: tmp/cache/webpacker 9 | check_yarn_integrity: false 10 | webpack_compile_output: false 11 | 12 | # Additional paths webpack should lookup modules 13 | # ['app/assets', 'engine/foo/app/assets'] 14 | resolved_paths: [] 15 | 16 | # Reload manifest.json on all requests so we reload latest compiled packs 17 | cache_manifest: false 18 | 19 | # Extract and emit a css file 20 | extract_css: true 21 | 22 | static_assets_extensions: 23 | - .jpg 24 | - .jpeg 25 | - .png 26 | - .gif 27 | - .tiff 28 | - .ico 29 | - .svg 30 | - .eot 31 | - .otf 32 | - .ttf 33 | - .woff 34 | - .woff2 35 | 36 | extensions: 37 | - .tsx 38 | - .ts 39 | - .jsx 40 | - .mjs 41 | - .js 42 | - .sass 43 | - .scss 44 | - .css 45 | - .module.sass 46 | - .module.scss 47 | - .module.css 48 | - .png 49 | - .svg 50 | - .gif 51 | - .jpeg 52 | - .jpg 53 | 54 | development: 55 | <<: *default 56 | compile: true 57 | 58 | # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules 59 | check_yarn_integrity: true 60 | 61 | # Reference: https://webpack.js.org/configuration/dev-server/ 62 | dev_server: 63 | https: false 64 | host: localhost 65 | port: 3035 66 | public: localhost:3035 67 | hmr: true 68 | # Inline should be set to true if using HMR 69 | inline: true 70 | overlay: true 71 | compress: true 72 | disable_host_check: true 73 | use_local_ip: false 74 | quiet: false 75 | headers: 76 | "Access-Control-Allow-Origin": "*" 77 | watch_options: 78 | ignored: "**/node_modules/**" 79 | 80 | test: 81 | <<: *default 82 | compile: true 83 | 84 | # Compile test packs to a separate directory 85 | public_output_path: packs-test 86 | 87 | production: 88 | <<: *default 89 | 90 | # Production depends on precompilation of packs prior to booting for performance. 91 | compile: false 92 | 93 | # Extract and emit a css file 94 | extract_css: true 95 | 96 | # Cache manifest.json for performance 97 | cache_manifest: true 98 | -------------------------------------------------------------------------------- /db/migrate/20170419034832_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | class DeviseCreateUsers < ActiveRecord::Migration[5.1] 2 | def change 3 | create_table :users do |t| 4 | ## Database authenticatable 5 | t.string :email, null: false, default: "" 6 | t.string :encrypted_password, null: false, default: "" 7 | 8 | ## Recoverable 9 | t.string :reset_password_token 10 | t.datetime :reset_password_sent_at 11 | 12 | ## Rememberable 13 | t.datetime :remember_created_at 14 | 15 | ## Trackable 16 | t.integer :sign_in_count, default: 0, null: false 17 | t.datetime :current_sign_in_at 18 | t.datetime :last_sign_in_at 19 | t.inet :current_sign_in_ip 20 | t.inet :last_sign_in_ip 21 | 22 | ## Confirmable 23 | # t.string :confirmation_token 24 | # t.datetime :confirmed_at 25 | # t.datetime :confirmation_sent_at 26 | # t.string :unconfirmed_email # Only if using reconfirmable 27 | 28 | ## Lockable 29 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 30 | # t.string :unlock_token # Only if unlock strategy is :email or :both 31 | # t.datetime :locked_at 32 | 33 | 34 | t.timestamps null: false 35 | end 36 | 37 | add_index :users, :email, unique: true 38 | add_index :users, :reset_password_token, unique: true 39 | # add_index :users, :confirmation_token, unique: true 40 | # add_index :users, :unlock_token, unique: true 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /db/migrate/20181003064422_rename_users_to_accounts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RenameUsersToAccounts < ActiveRecord::Migration[5.2] 4 | def change 5 | rename_table :users, :accounts 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181003065156_create_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateUsers < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :users, &:timestamps 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181003072918_add_authenticatable_references_to_accounts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddAuthenticatableReferencesToAccounts < ActiveRecord::Migration[5.2] 4 | def change 5 | add_reference :accounts, 6 | :authenticatable, 7 | polymorphic: true, 8 | index: true, 9 | null: false 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20220223222152_create_active_storage_tables.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20170806125915) 2 | class CreateActiveStorageTables < ActiveRecord::Migration[5.2] 3 | def change 4 | # Use Active Record's configured type for primary and foreign keys 5 | primary_key_type, foreign_key_type = primary_and_foreign_key_types 6 | 7 | create_table :active_storage_blobs, id: primary_key_type do |t| 8 | t.string :key, null: false 9 | t.string :filename, null: false 10 | t.string :content_type 11 | t.text :metadata 12 | t.string :service_name, null: false 13 | t.bigint :byte_size, null: false 14 | t.string :checksum 15 | 16 | if connection.supports_datetime_with_precision? 17 | t.datetime :created_at, precision: 6, null: false 18 | else 19 | t.datetime :created_at, null: false 20 | end 21 | 22 | t.index [ :key ], unique: true 23 | end 24 | 25 | create_table :active_storage_attachments, id: primary_key_type do |t| 26 | t.string :name, null: false 27 | t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type 28 | t.references :blob, null: false, type: foreign_key_type 29 | 30 | if connection.supports_datetime_with_precision? 31 | t.datetime :created_at, precision: 6, null: false 32 | else 33 | t.datetime :created_at, null: false 34 | end 35 | 36 | t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true 37 | t.foreign_key :active_storage_blobs, column: :blob_id 38 | end 39 | 40 | create_table :active_storage_variant_records, id: primary_key_type do |t| 41 | t.belongs_to :blob, null: false, index: false, type: foreign_key_type 42 | t.string :variation_digest, null: false 43 | 44 | t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true 45 | t.foreign_key :active_storage_blobs, column: :blob_id 46 | end 47 | end 48 | 49 | private 50 | def primary_and_foreign_key_types 51 | config = Rails.configuration.generators 52 | setting = config.options[config.orm][:primary_key_type] 53 | primary_key_type = setting || :primary_key 54 | foreign_key_type = setting || :bigint 55 | [primary_key_type, foreign_key_type] 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /db/migrate/20220223222236_add_service_name_to_active_storage_blobs.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20190112182829) 2 | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] 3 | def up 4 | unless column_exists?(:active_storage_blobs, :service_name) 5 | add_column :active_storage_blobs, :service_name, :string 6 | 7 | if configured_service = ActiveStorage::Blob.service.name 8 | ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) 9 | end 10 | 11 | change_column :active_storage_blobs, :service_name, :string, null: false 12 | end 13 | end 14 | 15 | def down 16 | remove_column :active_storage_blobs, :service_name 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20220223222237_create_active_storage_variant_records.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20191206030411) 2 | class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0] 3 | def change 4 | # Use Active Record's configured type for primary key 5 | create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t| 6 | t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type 7 | t.string :variation_digest, null: false 8 | 9 | t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true 10 | t.foreign_key :active_storage_blobs, column: :blob_id 11 | end 12 | end 13 | 14 | private 15 | def primary_key_type 16 | config = Rails.configuration.generators 17 | config.options[config.orm][:primary_key_type] || :primary_key 18 | end 19 | 20 | def blobs_primary_key_type 21 | pkey_name = connection.primary_key(:active_storage_blobs) 22 | pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name } 23 | pkey_column.bigint? ? :bigint : pkey_column.type 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20220223222238_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20211119233751) 2 | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] 3 | def change 4 | change_column_null(:active_storage_blobs, :checksum, true) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema[7.0].define(version: 2022_02_23_222238) do 14 | # These are extensions that must be enabled in order to support this database 15 | enable_extension "plpgsql" 16 | 17 | create_table "accounts", force: :cascade do |t| 18 | t.string "email", default: "", null: false 19 | t.string "encrypted_password", default: "", null: false 20 | t.string "reset_password_token" 21 | t.datetime "reset_password_sent_at", precision: nil 22 | t.datetime "remember_created_at", precision: nil 23 | t.integer "sign_in_count", default: 0, null: false 24 | t.datetime "current_sign_in_at", precision: nil 25 | t.datetime "last_sign_in_at", precision: nil 26 | t.inet "current_sign_in_ip" 27 | t.inet "last_sign_in_ip" 28 | t.datetime "created_at", precision: nil, null: false 29 | t.datetime "updated_at", precision: nil, null: false 30 | t.string "authenticatable_type", null: false 31 | t.bigint "authenticatable_id", null: false 32 | t.index ["authenticatable_type", "authenticatable_id"], name: "index_accounts_on_authenticatable_type_and_authenticatable_id" 33 | t.index ["email"], name: "index_accounts_on_email", unique: true 34 | t.index ["reset_password_token"], name: "index_accounts_on_reset_password_token", unique: true 35 | end 36 | 37 | create_table "active_storage_attachments", force: :cascade do |t| 38 | t.string "name", null: false 39 | t.string "record_type", null: false 40 | t.bigint "record_id", null: false 41 | t.bigint "blob_id", null: false 42 | t.datetime "created_at", null: false 43 | t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" 44 | t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true 45 | end 46 | 47 | create_table "active_storage_blobs", force: :cascade do |t| 48 | t.string "key", null: false 49 | t.string "filename", null: false 50 | t.string "content_type" 51 | t.text "metadata" 52 | t.string "service_name", null: false 53 | t.bigint "byte_size", null: false 54 | t.string "checksum" 55 | t.datetime "created_at", null: false 56 | t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true 57 | end 58 | 59 | create_table "active_storage_variant_records", force: :cascade do |t| 60 | t.bigint "blob_id", null: false 61 | t.string "variation_digest", null: false 62 | t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true 63 | end 64 | 65 | create_table "users", force: :cascade do |t| 66 | t.datetime "created_at", precision: nil, null: false 67 | t.datetime "updated_at", precision: nil, null: false 68 | end 69 | 70 | add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" 71 | add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" 72 | end 73 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | postgres: 5 | image: 'postgres:10.4-alpine' 6 | volumes: 7 | - 'postgres:/var/lib/postgresql/data' 8 | 9 | redis: 10 | image: 'redis:4.0-alpine' 11 | command: redis-server 12 | volumes: 13 | - 'redis:/data' 14 | 15 | app: 16 | depends_on: 17 | - 'postgres' 18 | - 'redis' 19 | build: . 20 | command: ['foreman', 'start', '-f', 'Procfile.docker'] 21 | ports: 22 | - '3000:5000' 23 | volumes: 24 | - 'gems_cache:/gems' 25 | - '.:/app' 26 | 27 | volumes: 28 | gems_cache: 29 | redis: 30 | postgres: 31 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Gems will be installed at runtime, NOT during the Docker build. This would not 4 | # be a good approach for production systems since the setup is not always 100% 5 | # reproducible, but it's much easier during development since new gems can be 6 | # added via editing the Gemfile locally and then issuing the following command: 7 | # $ docker-compose exec app bundle install 8 | 9 | # Exit on failure 10 | set -e 11 | 12 | # If necessary, install gems and their binstubs. `BUNDLE_BIN` is prepended to 13 | # `PATH`` in the Dockerfile. 14 | bundle check ||bundle install --binstubs="$BUNDLE_BIN" 15 | 16 | # Execute the command specified in `docker-compose.yml` 17 | exec "$@" 18 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | modulePaths: ["/"], 3 | rootDir: "./app/javascript", 4 | testEnvironment: "jsdom", 5 | }; 6 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/lib/assets/.keep -------------------------------------------------------------------------------- /lib/generators/decorator/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Generates a decorator for the given model. 3 | 4 | Examples: 5 | `rails generate decorator user` 6 | 7 | # app/decorator/user_decorator.rb 8 | class UserDecorator < ApplicationDecorator 9 | end 10 | 11 | `rails generate decorator user name email` 12 | 13 | # app/forms/user_decorator.rb 14 | class UserDecorator < ApplicationDecorator 15 | forward :name, :email 16 | end 17 | -------------------------------------------------------------------------------- /lib/generators/decorator/decorator_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DecoratorGenerator < Rails::Generators::NamedBase 4 | source_root File.expand_path('templates', __dir__) 5 | 6 | argument :forward_methods, type: :array, default: [] 7 | 8 | def create_decorator_file 9 | template( 10 | 'decorator.rb.tt', 11 | File.join('app', 'decorators', class_path, "#{file_name}_decorator.rb"), 12 | ) 13 | end 14 | 15 | private 16 | 17 | def forward_method_names 18 | forward_methods.map { |m| m.to_sym.inspect } 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/generators/decorator/templates/decorator.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <% module_namespacing do -%> 4 | class <%= class_name %>Decorator < ApplicationDecorator 5 | <% unless (forwards = forward_method_names.join(', ')).empty? -%> 6 | forward <%= forwards %> 7 | <% end -%> 8 | end 9 | <% end -%> 10 | -------------------------------------------------------------------------------- /lib/generators/form/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Generates a form for the given model. 3 | 4 | Examples: 5 | `rails generate form user` 6 | 7 | # app/forms/user_form.rb 8 | class UserForm < ApplicationForm 9 | end 10 | 11 | `rails generate form user name email` 12 | 13 | # app/forms/user_form.rb 14 | class UserForm < ApplicationForm 15 | form_attributes :name, :email 16 | end 17 | 18 | `rails generate form signup name email --resource User` 19 | `rails generate form signup name email -r User` 20 | 21 | # app/forms/signup_form.rb 22 | class SignupForm < ApplicationForm 23 | resource_class User 24 | 25 | form_attributes :name, :email 26 | end 27 | -------------------------------------------------------------------------------- /lib/generators/form/form_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class FormGenerator < Rails::Generators::NamedBase 4 | source_root File.expand_path('templates', __dir__) 5 | 6 | class_option :resource, 7 | type: :string, 8 | default: nil, 9 | aliases: '-r', 10 | banner: 'CLASS', 11 | desc: 'Specifies the resource class' 12 | argument :form_attributes, type: :array, default: [] 13 | 14 | def create_form_file 15 | template 'form.rb.tt', 16 | File.join('app', 'forms', class_path, "#{file_name}_form.rb") 17 | end 18 | 19 | private 20 | 21 | def resource_class_name 22 | options['resource'] 23 | end 24 | 25 | def form_attribute_names 26 | form_attributes.map { |a| a.to_sym.inspect } 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/generators/form/templates/form.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <% module_namespacing do -%> 4 | class <%= class_name %>Form < ApplicationForm 5 | <% if resource_class_name -%> 6 | resource_class <%= resource_class_name %> 7 | 8 | <% end -%> 9 | form_attributes <%= form_attribute_names.join(', ') %> 10 | end 11 | <% end -%> 12 | -------------------------------------------------------------------------------- /lib/generators/presenter/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Generates a presenter for the given model. 3 | 4 | Examples: 5 | `rails generate presenter user` 6 | 7 | # app/presenter/user_presenter.rb 8 | class UserPresenter < ApplicationPresenter 9 | end 10 | 11 | `rails generate presenter user name email` 12 | 13 | # app/forms/user_form.rb 14 | class UserPresenter < ApplicationPresenter 15 | forward :name, :email 16 | end 17 | -------------------------------------------------------------------------------- /lib/generators/presenter/presenter_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PresenterGenerator < Rails::Generators::NamedBase 4 | source_root File.expand_path('templates', __dir__) 5 | 6 | argument :forward_methods, type: :array, default: [] 7 | 8 | def create_presenter_file 9 | template( 10 | 'presenter.rb.tt', 11 | File.join('app', 'presenter', class_path, "#{file_name}_presenter.rb"), 12 | ) 13 | end 14 | 15 | private 16 | 17 | def forward_method_names 18 | forward_methods.map { |m| m.to_sym.inspect } 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/generators/presenter/templates/presenter.rb.tt: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | <% module_namespacing do -%> 4 | class <%= class_name %>Presenter < ApplicationPresenter 5 | <% unless (forwards = forward_method_names.join(', ')).empty? -%> 6 | forward <%= forwards %> 7 | <% end -%> 8 | end 9 | <% end -%> 10 | -------------------------------------------------------------------------------- /lib/rack/reject_trace.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Rack 4 | class RejectTrace 5 | def initialize(app) 6 | @app = app 7 | end 8 | 9 | def call(env) 10 | return @app.call(env) unless env['REQUEST_METHOD'] == 'TRACE' 11 | 12 | [405, {}, []] 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/lib/tasks/.keep -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/log/.keep -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rails_new", 3 | "private": true, 4 | "engines": { 5 | "node": "^16.13.0", 6 | "yarn": ">=1.9.0" 7 | }, 8 | "config": { 9 | "files": "app/javascript/**/*.{js,jsx,ts,tsx} app/assets/javascripts/**/*.{js,jsx,ts,tsx}" 10 | }, 11 | "scripts": { 12 | "dev": "./bin/webpack-dev-server", 13 | "lint-check": "eslint --format codeframe $npm_package_config_files && prettier --list-different $npm_package_config_files", 14 | "lint-write": "eslint --fix $npm_package_config_files && prettier --write $npm_package_config_files", 15 | "types-watch": "tsc --watch", 16 | "test": "jest --passWithNoTests" 17 | }, 18 | "dependencies": { 19 | "@babel/core": "^7.4.5", 20 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", 21 | "@babel/preset-react": "^7.0.0", 22 | "@babel/preset-typescript": "^7.3.3", 23 | "@rails/webpacker": "^4.0.7", 24 | "@sentry/browser": "^5.11.0", 25 | "@testing-library/react-hooks": "^3.2.1", 26 | "@types/react": "^16.8.17", 27 | "@types/react-dom": "^16.8.4", 28 | "babel-loader": "^8.0.6", 29 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 30 | "bootstrap": "^4.3.1", 31 | "core-js": "^3.0.1", 32 | "jquery": "^3.2.1", 33 | "jquery-ujs": "^1.2.2", 34 | "popper.js": "^1.12.9", 35 | "prop-types": "^15.7.2", 36 | "react": "^16.8.4", 37 | "react-dom": "npm:@hot-loader/react-dom", 38 | "react-hot-loader": "^4.8.4", 39 | "react_ujs": "^2.5.0", 40 | "typescript": "^3.7.0", 41 | "webpack": "^4.35.0" 42 | }, 43 | "devDependencies": { 44 | "@prettier/plugin-ruby": "^1.0.1", 45 | "@types/jest": "^25.1.4", 46 | "@typescript-eslint/eslint-plugin": "^2.0.0", 47 | "@typescript-eslint/parser": "^2.0.0", 48 | "eslint": "^5.16.0", 49 | "eslint-config-airbnb": "^17.1.0", 50 | "eslint-config-prettier": "^2.9.0", 51 | "eslint-config-standard": "^11.0.0", 52 | "eslint-plugin-import": "^2.2.0", 53 | "eslint-plugin-jsx-a11y": "^6.2.1", 54 | "eslint-plugin-node": "^9.1.0", 55 | "eslint-plugin-prettier": "^3.1.2", 56 | "eslint-plugin-promise": "^4.1.1", 57 | "eslint-plugin-react": "^7.0.1", 58 | "eslint-plugin-react-hooks": "^1.7.0", 59 | "eslint-plugin-standard": "^4.0.0", 60 | "jest": "^25.1.0", 61 | "prettier": "^2.0.0", 62 | "react-test-renderer": "^16.13.1", 63 | "webpack-cli": "^3.2.3", 64 | "webpack-dev-server": "^3.8.0" 65 | }, 66 | "resolutions": { 67 | "node-sass": "^6.0.1" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/android-chrome-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/android-chrome-144x144.png -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/android-chrome-36x36.png -------------------------------------------------------------------------------- /public/android-chrome-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/android-chrome-48x48.png -------------------------------------------------------------------------------- /public/android-chrome-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/android-chrome-72x72.png -------------------------------------------------------------------------------- /public/android-chrome-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/android-chrome-96x96.png -------------------------------------------------------------------------------- /public/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /public/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /public/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /public/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /public/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #ffffff 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/favicon-96x96.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/favicon.ico -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "icons": [ 4 | { 5 | "src": "\/android-chrome-36x36.png", 6 | "sizes": "36x36", 7 | "type": "image\/png", 8 | "density": "0.75" 9 | }, 10 | { 11 | "src": "\/android-chrome-48x48.png", 12 | "sizes": "48x48", 13 | "type": "image\/png", 14 | "density": "1.0" 15 | }, 16 | { 17 | "src": "\/android-chrome-72x72.png", 18 | "sizes": "72x72", 19 | "type": "image\/png", 20 | "density": "1.5" 21 | }, 22 | { 23 | "src": "\/android-chrome-96x96.png", 24 | "sizes": "96x96", 25 | "type": "image\/png", 26 | "density": "2.0" 27 | }, 28 | { 29 | "src": "\/android-chrome-144x144.png", 30 | "sizes": "144x144", 31 | "type": "image\/png", 32 | "density": "3.0" 33 | }, 34 | { 35 | "src": "\/android-chrome-192x192.png", 36 | "sizes": "192x192", 37 | "type": "image\/png", 38 | "density": "4.0" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /public/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/mstile-144x144.png -------------------------------------------------------------------------------- /public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/mstile-150x150.png -------------------------------------------------------------------------------- /public/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/mstile-310x310.png -------------------------------------------------------------------------------- /public/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/public/mstile-70x70.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /spec/decorators/application_decorator_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Decorator classes used in the tests below 4 | class TestUserDecorator1 < ApplicationDecorator 5 | forward :first_name, :last_name, age: :user_age 6 | forward :email, to: :@contact 7 | forward :email, to: :@contact, prefix: :contact 8 | 9 | def initialize(user) 10 | @contact = user.contact 11 | super 12 | end 13 | 14 | def full_name 15 | "#{first_name} #{last_name}" 16 | end 17 | end 18 | 19 | class TestUserDecorator2 < ApplicationDecorator 20 | forward_all 21 | end 22 | 23 | describe ApplicationDecorator do 24 | let(:user) do 25 | QuickStruct.new( 26 | first_name: 'Test', 27 | last_name: 'User', 28 | age: 42, 29 | contact: QuickStruct.new(email: 'test@example.com'), 30 | ) 31 | end 32 | 33 | describe '.forward' do 34 | let(:decorated_user) { TestUserDecorator1.new(user) } 35 | 36 | it 'forwards methods' do 37 | expect(decorated_user.first_name).to eq user.first_name 38 | expect(decorated_user.last_name).to eq user.last_name 39 | end 40 | 41 | it 'aliases methods' do 42 | expect(decorated_user.user_age).to eq user.age 43 | end 44 | 45 | it 'adds custom methods' do 46 | expect(decorated_user.full_name) 47 | .to eq "#{user.first_name} #{user.last_name}" 48 | end 49 | 50 | it 'can delegate to other objects' do 51 | expect(decorated_user.email).to eq user.contact.email 52 | end 53 | 54 | it 'can prefix delegated methods' do 55 | expect(decorated_user.contact_email).to eq user.contact.email 56 | end 57 | end 58 | 59 | describe '.forward_all' do 60 | let(:decorated_user) { TestUserDecorator2.new(user) } 61 | 62 | it 'forwards methods' do 63 | expect(decorated_user.first_name).to eq user.first_name 64 | expect(decorated_user.last_name).to eq user.last_name 65 | expect(decorated_user.age).to eq user.age 66 | end 67 | 68 | it 'responds to forwarded methods' do 69 | expect(decorated_user.respond_to?(:first_name)).to be true 70 | expect(decorated_user.respond_to?(:last_name)).to be true 71 | expect(decorated_user.respond_to?(:age)).to be true 72 | end 73 | end 74 | 75 | describe '.decorate_collection' do 76 | it 'wraps all elements of the collection in a decorator' do 77 | decorated = TestUserDecorator1.decorate_collection([user, user]) 78 | expect(decorated.size).to eq 2 79 | expect(decorated).to all(be_a TestUserDecorator1) 80 | end 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /spec/factories/accounts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | FactoryBot.define do 4 | factory :account do 5 | sequence(:email) { |n| "user#{n}@example.com" } 6 | password { '1234test' } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | FactoryBot.define do 4 | factory :user do 5 | after(:create) do |user, _evaluator| 6 | create(:account, authenticatable: user) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/forms/application_form_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Test form classes used below 4 | class TestAccount < Account; end 5 | 6 | class TestUser < User; end 7 | 8 | class TestAccountForm < ApplicationForm; end 9 | 10 | class SignupForm < ApplicationForm 11 | resource_class TestAccount 12 | 13 | attributes :name 14 | 15 | validates :name, presence: true 16 | end 17 | 18 | describe ApplicationForm do 19 | context 'class methods' do 20 | describe '.resource_class' do 21 | it 'correctly infers the model name' do 22 | expect(TestAccountForm.resource_class).to eq TestAccount 23 | end 24 | 25 | it 'uses an explicitly specified model name' do 26 | expect(SignupForm.resource_class).to eq TestAccount 27 | end 28 | 29 | it 'correctly returns all validators' do 30 | # Validated automatically by Devise. 31 | expect(SignupForm.validators_on(:email).size).to be > 0 32 | expect(SignupForm.validators_on(:name).size).to be > 0 33 | end 34 | end 35 | 36 | describe '.model_name' do 37 | it 'returns the resource class as ActiveModel::Name' do 38 | expect(TestAccountForm.model_name).to be_a(ActiveModel::Name) 39 | end 40 | end 41 | end 42 | 43 | context 'instance methods' do 44 | describe '#resource' do 45 | it 'returns the resource wrapped by the form object' do 46 | form = TestAccountForm.new(Account.new, email: 'test@example.com') 47 | expect(form.resource).to be_a(Account) 48 | end 49 | end 50 | end 51 | 52 | context 'delegation' do 53 | it 'delegates the persisted? method to the wrapped object' do 54 | form = TestAccountForm.new(Account.new, email: 'test@example.com') 55 | expect(form.persisted?).to be false 56 | end 57 | end 58 | 59 | context 'validations' do 60 | it 'is valid if the form and resource are valid' do 61 | user = TestUser.new 62 | account = TestAccount.new( 63 | email: 'test@example.com', password: 's3cr3t!', authenticatable: user, 64 | ) 65 | params = 66 | ActionController::Parameters.new(name: 'Test Account').permit(:name) 67 | form = SignupForm.new(account, params) 68 | expect(form).to be_valid 69 | expect(form.resource).to be_valid 70 | allow(account).to receive(:save!).and_call_original 71 | form.save 72 | expect(account).to have_received(:save!) 73 | end 74 | 75 | it 'is invalid if a form validation fails' do 76 | form = SignupForm.new 77 | 78 | expect(form).not_to be_valid 79 | expect(form.errors[:name]).to be_present 80 | end 81 | 82 | it 'propagates errors of the wrapped resource' do 83 | params = 84 | ActionController::Parameters.new(name: 'Test Account').permit(:name) 85 | form = SignupForm.new(TestAccount.new, params) 86 | 87 | expect(form.save).to be false 88 | expect(form.errors[:email]).to be_present 89 | expect(form.errors[:password]).to be_present 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /spec/models/account_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe Account do 4 | it 'sends transactional emails asynchronously' do 5 | account = described_class.find_by(authenticatable: create(:user)) 6 | expect { account.send_reset_password_instructions } 7 | .to change(Sidekiq::Queues['mailers'], :size).by 1 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/policies/application_policy_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TestUser < User; end 4 | 5 | class TestUserPresenter < ApplicationPresenter; end 6 | 7 | describe ApplicationPolicy do 8 | it 'implicitly unwraps decorators and presenters' do 9 | current_user = User.new 10 | presented_user = TestUser.new 11 | user_presenter = TestUserPresenter.new(presented_user) 12 | policy = described_class.new(current_user, user_presenter) 13 | expect(policy.record).to eq(presented_user) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/presenters/application_presenter_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Presenter class used in the tests below. Note that decorator base class 4 | # behavior is not retested here. 5 | class TestUserPresenter < ApplicationPresenter 6 | forward :first_name, :last_name, :age 7 | 8 | def formatted_first_name 9 | tag.strong first_name 10 | end 11 | end 12 | 13 | describe ApplicationPresenter do 14 | let(:user) { QuickStruct.new(first_name: 'Test', last_name: 'User', age: 42) } 15 | 16 | describe '.call' do 17 | context 'without a block' do 18 | it 'returns the wrapped instance' do 19 | user_presenter = TestUserPresenter.(user) 20 | expect(user_presenter).to be_a(TestUserPresenter) 21 | end 22 | 23 | it 'uses imported view helpers' do 24 | user_presenter = TestUserPresenter.(user) 25 | formatted_first_name = "#{user.first_name}" 26 | expect(user_presenter.formatted_first_name).to eq formatted_first_name 27 | end 28 | end 29 | 30 | context 'with a block' do 31 | it 'yield the instance to the provided block' do 32 | expect { |block| TestUserPresenter.(user, &block) }.to yield_control 33 | end 34 | 35 | it 'returns the wrapped instance' do 36 | user_presenter = TestUserPresenter.(user) {} # no-op block 37 | expect(user_presenter).to be_a(TestUserPresenter) 38 | end 39 | end 40 | end 41 | 42 | describe '.present_collection' do 43 | it 'wraps all provided models in a presenter' do 44 | user_presenters = TestUserPresenter.present_collection([user, user]) 45 | expect(user_presenters.size).to eq 2 46 | expect(user_presenters).to all(be_a(TestUserPresenter)) 47 | end 48 | 49 | it 'yields each element to a provided block' do 50 | output = StringIO.new 51 | user_presenters = 52 | TestUserPresenter.present_collection([user, user]) do |u| 53 | output.puts(u.first_name) 54 | end 55 | output.rewind 56 | expect(output.string).to eq "Test\nTest\n" 57 | expect(user_presenters.size).to eq 2 58 | expect(user_presenters).to all(be_a(TestUserPresenter)) 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /spec/rails_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is copied to spec/ when you run 'rails generate rspec:install' 4 | ENV['RAILS_ENV'] ||= 'test' 5 | require File.expand_path('../config/environment', __dir__) 6 | 7 | # Prevent database truncation if the environment is production 8 | if Rails.env.production? 9 | abort('The Rails environment is running in production mode!') 10 | end 11 | 12 | require 'spec_helper' 13 | require 'rspec/rails' 14 | # Add additional requires below this line. Rails is not loaded until this point! 15 | require 'webmock/rspec' 16 | require 'sidekiq/testing' 17 | 18 | WebMock.disable_net_connect!( 19 | # NOTE: The webdrivers gem looks for updates to our driver(s) automatically 20 | # when we run our specs so we need to allow calls to the driver hosts. For 21 | # now we only need the chromedriver: 22 | allow: 'chromedriver.storage.googleapis.com', 23 | # NOTE: System tests break if we don't allow localhost: 24 | allow_localhost: true, 25 | ) 26 | 27 | # Requires supporting ruby files with custom matchers and macros, etc, in 28 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are 29 | # run as spec files by default. This means that files in spec/support that end 30 | # in _spec.rb will both be required and run as specs, causing the specs to be 31 | # run twice. It is recommended that you do not name files matching this glob to 32 | # end with _spec.rb. You can configure this pattern with the --pattern 33 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. 34 | # 35 | # The following line is provided for convenience purposes. It has the downside 36 | # of increasing the boot-up time by auto-requiring all files in the support 37 | # directory. Alternatively, in the individual `*_spec.rb` files, manually 38 | # require only the support files necessary. 39 | # 40 | Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } 41 | 42 | # Checks for pending migration and applies them before tests are run. 43 | # If you are not using ActiveRecord, you can remove this line. 44 | ActiveRecord::Migration.maintain_test_schema! 45 | 46 | RSpec.configure do |config| 47 | # Allow the use of t() and l() in specs instead of using hard-coded strings 48 | # or needing the full I18n.t() syntax. 49 | config.include AbstractController::Translation 50 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 51 | # config.fixture_path = "#{::Rails.root}/spec/fixtures" 52 | 53 | # If you're not using ActiveRecord, or you'd prefer not to run each of your 54 | # examples within a transaction, remove the following line or assign false 55 | # instead of true. 56 | config.use_transactional_fixtures = true 57 | 58 | config.before do 59 | # Avoid inadvertent leftover jobs. 60 | Sidekiq::Worker.clear_all 61 | # Reset this to the default so you don't need to clean up specs that want 62 | # inline jobs. 63 | Sidekiq::Testing.fake! 64 | # Avoid inadvertent leftover mail. 65 | ActionMailer::Base.deliveries.clear 66 | end 67 | 68 | # RSpec Rails can automatically mix in different behaviours to your tests 69 | # based on their file location, for example enabling you to call `get` and 70 | # `post` in specs under `spec/controllers`. 71 | # 72 | # You can disable this behaviour by removing the line below, and instead 73 | # explicitly tag your specs with their type, e.g.: 74 | # 75 | # RSpec.describe UsersController, :type => :controller do 76 | # # ... 77 | # end 78 | # 79 | # The different available types are documented in the features, such as in 80 | # https://relishapp.com/rspec/rspec-rails/docs 81 | config.infer_spec_type_from_file_location! 82 | 83 | # Filter lines from Rails gems in backtraces. 84 | config.filter_rails_from_backtrace! 85 | # arbitrary gems may also be filtered via: 86 | # config.filter_gems_from_backtrace("gem name") 87 | 88 | # System tests use Rack::Test for non JS test and headless Chrome for JS specs 89 | config.before(:each, type: :system) do 90 | driven_by :rack_test 91 | end 92 | 93 | config.before(:each, type: :system, js: true) do 94 | driven_by :selenium_chrome_headless 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'simplecov' 4 | 5 | if ENV['CIRCLE_ARTIFACTS'] 6 | dir = File.join(ENV.fetch('CIRCLE_ARTIFACTS', nil), 'coverage') 7 | SimpleCov.coverage_dir(dir) 8 | end 9 | 10 | SimpleCov.start 'rails' do 11 | add_filter '/config/' 12 | add_filter '/spec/' 13 | add_filter '/vendor/' 14 | end 15 | 16 | # This file was generated by the `rails generate rspec:install` command. Conventionally, all 17 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 18 | # The generated `.rspec` file contains `--require spec_helper` which will cause 19 | # this file to always be loaded, without a need to explicitly require it in any 20 | # files. 21 | # 22 | # Given that it is always loaded, you are encouraged to keep this file as 23 | # light-weight as possible. Requiring heavyweight dependencies from this file 24 | # will add to the boot time of your test suite on EVERY test run, even for an 25 | # individual file that may not need all of that loaded. Instead, consider making 26 | # a separate helper file that requires the additional dependencies and performs 27 | # the additional setup, and require it from the spec files that actually need 28 | # it. 29 | # 30 | # The `.rspec` file also contains a few flags that are not defaults but that 31 | # users commonly want. 32 | # 33 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 34 | RSpec.configure do |config| 35 | # rspec-expectations config goes here. You can use an alternate 36 | # assertion/expectation library such as wrong or the stdlib/minitest 37 | # assertions if you prefer. 38 | config.expect_with :rspec do |expectations| 39 | # This option will default to `true` in RSpec 4. It makes the `description` 40 | # and `failure_message` of custom matchers include text for helper methods 41 | # defined using `chain`, e.g.: 42 | # be_bigger_than(2).and_smaller_than(4).description 43 | # # => "be bigger than 2 and smaller than 4" 44 | # ...rather than: 45 | # # => "be bigger than 2" 46 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 47 | end 48 | 49 | # rspec-mocks config goes here. You can use an alternate test double 50 | # library (such as bogus or mocha) by changing the `mock_with` option here. 51 | config.mock_with :rspec do |mocks| 52 | # Prevents you from mocking or stubbing a method that does not exist on 53 | # a real object. This is generally recommended, and will default to 54 | # `true` in RSpec 4. 55 | mocks.verify_partial_doubles = true 56 | end 57 | 58 | # This option will default to `:apply_to_host_groups` in RSpec 4 (and will 59 | # have no way to turn it off -- the option exists only for backwards 60 | # compatibility in RSpec 3). It causes shared context metadata to be 61 | # inherited by the metadata hash of host groups and examples, rather than 62 | # triggering implicit auto-inclusion in groups with matching metadata. 63 | config.shared_context_metadata_behavior = :apply_to_host_groups 64 | 65 | # The settings below are suggested to provide a good initial experience 66 | # with RSpec, but feel free to customize to your heart's content. 67 | # # This allows you to limit a spec run to individual examples or groups 68 | # # you care about by tagging them with `:focus` metadata. When nothing 69 | # # is tagged with `:focus`, all examples get run. RSpec also provides 70 | # # aliases for `it`, `describe`, and `context` that include `:focus` 71 | # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. 72 | # config.filter_run_when_matching :focus 73 | # 74 | # # Allows RSpec to persist some state between runs in order to support 75 | # # the `--only-failures` and `--next-failure` CLI options. We recommend 76 | # # you configure your source control system to ignore this file. 77 | # config.example_status_persistence_file_path = "spec/examples.txt" 78 | # 79 | # # Limits the available syntax to the non-monkey patched syntax that is 80 | # # recommended. For more details, see: 81 | # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ 82 | # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ 83 | # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode 84 | # config.disable_monkey_patching! 85 | # 86 | # # Many RSpec users commonly either run the entire suite or an individual 87 | # # file, and it's useful to allow more verbose output when running an 88 | # # individual spec file. 89 | # if config.files_to_run.one? 90 | # # Use the documentation formatter for detailed output, 91 | # # unless a formatter has already been configured 92 | # # (e.g. via a command-line flag). 93 | # config.default_formatter = 'doc' 94 | # end 95 | # 96 | # # Print the 10 slowest examples and example groups at the 97 | # # end of the spec run, to help surface which specs are running 98 | # # particularly slow. 99 | # config.profile_examples = 10 100 | # 101 | # # Run specs in random order to surface order dependencies. If you find an 102 | # # order dependency and want to debug it, you can fix the order by providing 103 | # # the seed, which is printed after each run. 104 | # # --seed 1234 105 | # config.order = :random 106 | # 107 | # # Seed global randomization in this process using the `--seed` CLI option. 108 | # # Setting this allows you to use `--seed` to deterministically reproduce 109 | # # test failures related to randomization by passing the same `--seed` value 110 | # # as the one that triggered the failure. 111 | # Kernel.srand config.seed 112 | end 113 | -------------------------------------------------------------------------------- /spec/support/active_storage_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ActiveStorageHelper 4 | extend ActionDispatch::TestProcess 5 | 6 | def self.attach(name, type) 7 | file_path = Rails.root.join('spec', 'fixtures', 'files', name) 8 | fixture_file_upload(file_path, type) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/support/bullet.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # See: https://github.com/flyerhzm/bullet#run-in-tests 4 | if Bullet.enable? 5 | RSpec.configure do |config| 6 | config.before do 7 | Bullet.start_request 8 | end 9 | 10 | config.after do 11 | Bullet.perform_out_of_channel_notifications if Bullet.notification? 12 | Bullet.end_request 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/support/devise.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | config.include Devise::Test::ControllerHelpers, type: :controller 5 | config.include Devise::Test::IntegrationHelpers, type: :system 6 | end 7 | -------------------------------------------------------------------------------- /spec/support/factory_bot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | config.include FactoryBot::Syntax::Methods 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'helpers/response_helpers' 4 | require_relative 'helpers/session_helpers' 5 | 6 | RSpec.configure do |config| 7 | config.include SpecHelpers::SessionHelpers, type: :system 8 | config.include SpecHelpers::ResponseHelpers, type: :request 9 | end 10 | -------------------------------------------------------------------------------- /spec/support/helpers/response_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module SpecHelpers 4 | module ResponseHelpers 5 | def response_json 6 | response.parsed_body 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/support/helpers/session_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module SpecHelpers 4 | module SessionHelpers 5 | def sign_up_with(email, password, confirmation) 6 | visit(new_user_registration_path) 7 | fill_in('Email', with: email) 8 | fill_in('Password', with: password) 9 | fill_in('Password confirmation', with: confirmation) 10 | click_button('Sign up') 11 | end 12 | 13 | def sign_in_with(email, password) 14 | visit(new_user_session_path) 15 | fill_in('Email', with: email) 16 | fill_in('Password', with: password) 17 | click_button('Log in') 18 | end 19 | 20 | def fill_sign_in_form(email, password) 21 | fill_in('Email', with: email) 22 | fill_in('Password', with: password) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/support/shared_contexts/signed_in_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.shared_context 'signed in user' do 4 | include Warden::Test::Helpers 5 | 6 | before do 7 | Warden.test_mode! 8 | login_as(Account.find_by(authenticatable: @user), scope: :account) 9 | end 10 | 11 | after do 12 | Warden.test_reset! 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/support/shared_examples/api_requests.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | shared_examples 'a successful resource request' do |root| 4 | it 'returns an OK (200) status code' do 5 | expect(response.status).to eq(200) 6 | end 7 | 8 | it 'returns the resource' do 9 | expect(response_json[root]).to be_a Hash 10 | end 11 | end 12 | 13 | shared_examples 'a successful resource list request' do |root| 14 | it 'returns an OK (200) status code' do 15 | expect(response.status).to eq(200) 16 | end 17 | 18 | it 'returns the resource list' do 19 | expect(response_json[root]).to be_a Array 20 | end 21 | end 22 | 23 | shared_examples 'a successful resource create' do |root| 24 | it 'returns a Created (201) status code' do 25 | expect(response.status).to eq(201) 26 | end 27 | 28 | it 'returns the new resource' do 29 | expect(response_json[root]).to be_a Hash 30 | end 31 | end 32 | 33 | shared_examples 'an unsuccessful resource create' do 34 | it 'returns an Unprocessable Entity (422) status code' do 35 | expect(response.status).to eq(422) 36 | end 37 | end 38 | 39 | shared_examples 'an unsuccessful resource update' do 40 | it 'returns an Unprocessable Entity (422) status code' do 41 | expect(response.status).to eq(422) 42 | end 43 | end 44 | 45 | shared_examples 'an unauthorized request' do 46 | it 'returns an Unauthorized (401) response code' do 47 | expect(response.status).to be 401 48 | end 49 | end 50 | 51 | shared_examples 'a forbidden request' do 52 | it 'returns a Forbidden (403) status code' do 53 | expect(response.status).to be 403 54 | end 55 | end 56 | 57 | shared_examples 'a resource was not found' do 58 | it 'returns a Not Found (404) status code' do 59 | expect(response.status).to be 404 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /spec/support/shoulda_matchers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Shoulda::Matchers.configure do |config| 4 | config.integrate do |with| 5 | with.test_framework :rspec 6 | with.library :rails 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/tmp/.keep -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "allowSyntheticDefaultImports": true, 7 | "noEmit": true, 8 | "lib": ["es6", "dom"], 9 | "module": "es6", 10 | "moduleResolution": "node", 11 | "sourceMap": true, 12 | "target": "es5", 13 | "jsx": "react" 14 | }, 15 | "exclude": ["node_modules", "vendor", "public"], 16 | "compileOnSave": false 17 | } 18 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockstep/rails_new/80cdf9b886484b784742faff6cabcba936aca822/vendor/.keep --------------------------------------------------------------------------------