├── .dockerignore ├── .env.example ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── ci.yml │ └── docker.yml ├── .gitignore ├── .rubocop.yml ├── .ruby-version ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── Procfile ├── Procfile.dev ├── README.md ├── Rakefile ├── app ├── assets │ ├── config │ │ └── manifest.js │ ├── images │ │ └── .keep │ └── stylesheets │ │ ├── actiontext.css │ │ └── application.css ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── controllers │ ├── application_controller.rb │ ├── articles_controller.rb │ ├── comments_controller.rb │ ├── concerns │ │ └── .keep │ └── welcome_controller.rb ├── helpers │ ├── application_helper.rb │ ├── articles_helper.rb │ ├── comments_helper.rb │ └── welcome_helper.rb ├── javascript │ ├── application.js │ └── controllers │ │ ├── application.js │ │ ├── hello_controller.js │ │ └── index.js ├── jobs │ └── application_job.rb ├── mailers │ └── application_mailer.rb ├── models │ ├── application_record.rb │ ├── article.rb │ ├── comment.rb │ └── concerns │ │ └── .keep └── views │ ├── active_storage │ └── blobs │ │ └── _blob.html.erb │ ├── articles │ ├── _article.html.erb │ ├── _article.json.jbuilder │ ├── _comments.html.erb │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.json.jbuilder │ ├── new.html.erb │ ├── show.html.erb │ └── show.json.jbuilder │ ├── comments │ ├── _comment.html.erb │ └── _new.html.erb │ ├── layouts │ ├── action_text │ │ └── contents │ │ │ └── _content.html.erb │ ├── application.html.erb │ ├── mailer.html.erb │ └── mailer.text.erb │ └── welcome │ └── index.html.erb ├── bin ├── brakeman ├── bundle ├── docker-entrypoint ├── docker-entrypoint-development ├── importmap ├── rails ├── rake ├── rspec ├── rubocop └── setup ├── compose.yaml ├── config.ru ├── config ├── application.rb ├── boot.rb ├── cable.yml ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── importmap.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── content_security_policy.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── permissions_policy.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── puma.rb ├── routes.rb └── storage.yml ├── db ├── migrate │ ├── 20210926221100_create_articles.rb │ ├── 20211216184102_create_active_storage_tables.active_storage.rb │ ├── 20211216184103_create_action_text_tables.action_text.rb │ ├── 20211216185503_create_comments.rb │ ├── 20230326154217_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20230326154218_create_active_storage_variant_records.active_storage.rb │ └── 20230326154219_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb ├── schema.rb └── seeds.rb ├── development.Dockerfile ├── heroku.yml ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── log └── .keep ├── public ├── 404.html ├── 406-unsupported-browser.html ├── 422.html ├── 500.html ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── favicon.ico ├── icon.png ├── icon.svg └── robots.txt ├── render.yaml ├── renovate.json ├── spec ├── helpers │ ├── articles_helper_spec.rb │ ├── comments_helper_spec.rb │ └── welcome_helper_spec.rb ├── models │ ├── article_spec.rb │ └── comment_spec.rb ├── rails_helper.rb ├── requests │ ├── articles_spec.rb │ ├── comments_spec.rb │ └── welcome_spec.rb ├── routing │ └── articles_routing_spec.rb ├── spec_helper.rb └── views │ └── articles │ ├── edit.html.erb_spec.rb │ ├── index.html.erb_spec.rb │ ├── new.html.erb_spec.rb │ └── show.html.erb_spec.rb ├── storage └── .keep ├── tmp ├── .keep └── pids │ └── .keep └── vendor ├── .keep └── javascript └── .keep /.dockerignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/.dockerignore -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | PGHOST=db 2 | PGUSER=postgres 3 | PGPASSWORD=changeme 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.rb diff=ruby 2 | *.gemspec diff=ruby 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: docker 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: bundler 8 | directory: "/" 9 | schedule: 10 | interval: daily 11 | ignore: 12 | - dependency-name: "rails" 13 | update-types: ["version-update:semver-major", "version-update:semver-minor"] 14 | - package-ecosystem: github-actions 15 | directory: "/" 16 | schedule: 17 | interval: daily 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | scan_ruby: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Set up Ruby 18 | uses: ruby/setup-ruby@v1 19 | with: 20 | bundler-cache: true 21 | 22 | - name: Scan for security vulnerabilities in Ruby dependencies 23 | run: | 24 | bundle exec bundler-audit --update 25 | bin/brakeman -q -w2 --no-pager 26 | 27 | lint: 28 | runs-on: ubuntu-latest 29 | 30 | env: 31 | DISABLE_BOOTSNAP: true 32 | DISABLE_BOOTSNAP_LOAD_PATH_CACHE: true 33 | 34 | steps: 35 | - uses: actions/checkout@v4 36 | 37 | - name: Set up Ruby 38 | uses: ruby/setup-ruby@v1 39 | with: 40 | bundler-cache: true 41 | 42 | - name: Run linters 43 | run: bin/rubocop --parallel 44 | 45 | test: 46 | runs-on: ubuntu-latest 47 | 48 | env: 49 | RAILS_ENV: test 50 | DATABASE_URL: postgres://postgres:postgres@localhost:5432 51 | DISABLE_BOOTSNAP: true 52 | DISABLE_BOOTSNAP_LOAD_PATH_CACHE: true 53 | 54 | services: 55 | postgres: 56 | image: postgres:17 57 | env: 58 | POSTGRES_PASSWORD: postgres 59 | options: >- 60 | --health-cmd pg_isready 61 | --health-interval 10s 62 | --health-timeout 5s 63 | --health-retries 5 64 | ports: 65 | - 5432:5432 66 | 67 | steps: 68 | - uses: actions/checkout@v4 69 | 70 | - name: Set up Ruby 71 | uses: ruby/setup-ruby@v1 72 | with: 73 | bundler-cache: true 74 | 75 | - name: Create database 76 | run: | 77 | bin/rails db:test:prepare 78 | 79 | - name: Run tests 80 | run: bundle exec rake 81 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | TEST_TAG: rails-on-docker:test 11 | 12 | jobs: 13 | build-and-test-image: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | 19 | - name: Set up QEMU 20 | uses: docker/setup-qemu-action@v3 21 | 22 | - name: Set up Docker Buildx 23 | uses: docker/setup-buildx-action@v3 24 | 25 | - name: Build and push 26 | uses: docker/build-push-action@v6 27 | with: 28 | push: false 29 | load: true 30 | tags: ${{ env.TEST_TAG }} 31 | cache-from: type=gha 32 | cache-to: type=gha,mode=max 33 | 34 | - name: Inspect 35 | run: | 36 | docker image inspect ${{ env.TEST_TAG }} 37 | 38 | - name: Start 39 | run: | 40 | docker run -d --rm --name=rails-on-docker --env SECRET_KEY_BASE=dummy ${{ env.TEST_TAG }} 41 | 42 | - name: Logs 43 | run: | 44 | docker ps 45 | docker logs rails-on-docker 46 | 47 | - name: Check Health 48 | run: | 49 | for i in {1..30}; do 50 | status=$(docker inspect --format='{{.State.Health.Status}}' rails-on-docker) 51 | if [ "$status" = "healthy" ]; then 52 | echo "Container is healthy" 53 | exit 0 54 | elif [ "$status" = "unhealthy" ]; then 55 | echo "Container is unhealthy" 56 | exit 1 57 | fi 58 | sleep 1 59 | done 60 | echo "Timed out waiting for container to become healthy" 61 | exit 1 62 | 63 | - name: Logs 64 | run: | 65 | docker logs rails-on-docker 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | capybara-*.html 3 | .rspec 4 | /db/*.sqlite3 5 | /db/*.sqlite3-journal 6 | /db/*.sqlite3-[0-9]* 7 | /public/system 8 | /coverage/ 9 | /spec/tmp 10 | *.orig 11 | rerun.txt 12 | pickle-email-*.html 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | /tmp/* 17 | !/log/.keep 18 | !/tmp/.keep 19 | /tmp/pids/* 20 | !/tmp/pids 21 | !/tmp/pids/.keep 22 | 23 | # TODO Comment out this rule if you are OK with secrets being uploaded to the repo 24 | config/initializers/secret_token.rb 25 | config/master.key 26 | 27 | # Only include if you have production secrets in this file, which is no longer a Rails default 28 | # config/secrets.yml 29 | 30 | # dotenv 31 | # TODO Comment out this rule if environment variables can be committed 32 | .env 33 | 34 | ## Environment normalization: 35 | /.bundle 36 | /vendor/bundle 37 | 38 | # these should all be checked in to normalize the environment: 39 | # Gemfile.lock, .ruby-version, .ruby-gemset 40 | 41 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 42 | .rvmrc 43 | 44 | # if using bower-rails ignore default bower_components path bower.json files 45 | /vendor/assets/bower_components 46 | *.bowerrc 47 | bower.json 48 | 49 | # Ignore pow environment settings 50 | .powenv 51 | 52 | # Ignore Byebug command history file. 53 | .byebug_history 54 | 55 | # Ignore node_modules 56 | node_modules/ 57 | 58 | # Ignore precompiled javascript packs 59 | /public/packs 60 | /public/packs-test 61 | /public/assets 62 | 63 | # Ignore yarn files 64 | /yarn-error.log 65 | yarn-debug.log* 66 | .yarn-integrity 67 | 68 | # Ignore uploaded files in development 69 | /storage/* 70 | !/storage/.keep 71 | 72 | /config/master.key 73 | 74 | .DS_Store 75 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-rails 3 | - rubocop-rspec 4 | 5 | # Omakase Ruby styling for Rails 6 | inherit_gem: 7 | rubocop-rails-omakase: rubocop.yml 8 | 9 | AllCops: 10 | TargetRubyVersion: 3.4.2 11 | TargetRailsVersion: 7.2.2 12 | DisabledByDefault: true 13 | Exclude: 14 | - "bin/**/*" 15 | - "vendor/**/*" 16 | - "public/**/*" 17 | - "node_modules/**/*" 18 | 19 | Bundler: 20 | Enabled: true 21 | 22 | Layout/EmptyLineAfterMagicComment: 23 | Enabled: true 24 | Layout/TrailingEmptyLines: 25 | Enabled: true 26 | Layout/TrailingWhitespace: 27 | Enabled: true 28 | 29 | Lint/BinaryOperatorWithIdenticalOperands: 30 | Enabled: true 31 | Lint/CircularArgumentReference: 32 | Enabled: true 33 | Lint/Debugger: 34 | Enabled: true 35 | Lint/DeprecatedClassMethods: 36 | Enabled: true 37 | Lint/DuplicateMethods: 38 | Enabled: false 39 | Lint/DuplicateHashKey: 40 | Enabled: true 41 | Lint/EachWithObjectArgument: 42 | Enabled: true 43 | Lint/ElseLayout: 44 | Enabled: true 45 | Lint/EmptyEnsure: 46 | Enabled: true 47 | Lint/EmptyInterpolation: 48 | Enabled: true 49 | Lint/EnsureReturn: 50 | Enabled: true 51 | Lint/FloatOutOfRange: 52 | Enabled: true 53 | Lint/FormatParameterMismatch: 54 | Enabled: true 55 | Lint/LiteralAsCondition: 56 | Enabled: true 57 | Lint/LiteralInInterpolation: 58 | Enabled: true 59 | Lint/Loop: 60 | Enabled: true 61 | Lint/NextWithoutAccumulator: 62 | Enabled: true 63 | Lint/RandOne: 64 | Enabled: true 65 | Lint/RequireParentheses: 66 | Enabled: true 67 | Lint/RescueException: 68 | Enabled: true 69 | Lint/RedundantStringCoercion: 70 | Enabled: false 71 | Lint/RedundantCopDisableDirective: 72 | Enabled: true 73 | Lint/RedundantSplatExpansion: 74 | Enabled: false 75 | Lint/UnreachableCode: 76 | Enabled: true 77 | Lint/UselessSetterCall: 78 | Enabled: true 79 | Lint/Void: 80 | Enabled: true 81 | 82 | Naming/ClassAndModuleCamelCase: 83 | Enabled: true 84 | 85 | # Security/Eval: 86 | # Enabled: false 87 | # Security/JSONLoad: 88 | # Enabled: true 89 | # Security/MarshalLoad: 90 | # Enabled: true 91 | # Security/Open: 92 | # Enabled: false 93 | # Security/YAMLLoad: 94 | # Enabled: false 95 | 96 | # Style/EndBlock: 97 | # Enabled: true 98 | # Style/HashSyntax: 99 | # Enabled: true 100 | # Style/StringLiterals: 101 | # Enabled: true 102 | # EnforcedStyle: "double_quotes" 103 | # Exclude: 104 | # - "config/**/*.rb" 105 | # - Rakefile 106 | # Style/CaseEquality: 107 | # Enabled: true 108 | # Style/ClassMethods: 109 | # Enabled: true 110 | # Style/ClassVars: 111 | # Enabled: true 112 | # Style/CollectionMethods: 113 | # Enabled: true 114 | # PreferredMethods: 115 | # collect: "map" 116 | # collect!: "map!" 117 | # inject: "reduce" 118 | # detect: "find" 119 | # find_all: "select" 120 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.2 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | # check=error=true 3 | 4 | # This Dockerfile is designed for production, not development. 5 | # docker build -t my-app . 6 | # docker run -d -p 80:80 -p 443:443 --name my-app -e RAILS_MASTER_KEY= my-app 7 | 8 | # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile 9 | ARG RUBY_VERSION=3.4.2 10 | FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base 11 | 12 | # Rails app lives here 13 | WORKDIR /rails 14 | 15 | # Install base packages 16 | RUN apt-get update -qq && \ 17 | apt-get install --no-install-recommends -y curl libjemalloc2 libvips postgresql-client && \ 18 | rm -rf /var/lib/apt/lists /var/cache/apt/archives 19 | 20 | # Set production environment 21 | ENV RAILS_ENV="production" \ 22 | BUNDLE_DEPLOYMENT="1" \ 23 | BUNDLE_PATH="/usr/local/bundle" \ 24 | BUNDLE_WITHOUT="development" 25 | 26 | # Throw-away build stage to reduce size of final image 27 | FROM base AS build 28 | 29 | # Install packages needed to build gems 30 | RUN apt-get update -qq && \ 31 | apt-get install --no-install-recommends -y build-essential git libpq-dev pkg-config libyaml-dev && \ 32 | rm -rf /var/lib/apt/lists /var/cache/apt/archives 33 | 34 | # Install application gems 35 | COPY Gemfile Gemfile.lock ./ 36 | RUN bundle install && \ 37 | rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ 38 | bundle exec bootsnap precompile --gemfile 39 | 40 | # Copy application code 41 | COPY . . 42 | 43 | # Precompile bootsnap code for faster boot times 44 | RUN bundle exec bootsnap precompile app/ lib/ 45 | 46 | # Precompiling assets for production without requiring secret RAILS_MASTER_KEY 47 | RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile 48 | 49 | 50 | # Final stage for app image 51 | FROM base 52 | 53 | # Copy built artifacts: gems, application 54 | COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" 55 | COPY --from=build /rails /rails 56 | 57 | # Run and own only the runtime files as a non-root user for security 58 | RUN groupadd --system --gid 1000 rails && \ 59 | useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \ 60 | chown -R rails:rails db log storage tmp 61 | USER 1000:1000 62 | 63 | # Entrypoint prepares the database. 64 | ENTRYPOINT ["/rails/bin/docker-entrypoint"] 65 | 66 | HEALTHCHECK --interval=15s --timeout=3s --start-period=0s --start-interval=5s --retries=3 \ 67 | CMD curl -f http://localhost:3000/up || exit 1 68 | # Start the server by default, this can be overwritten at runtime 69 | EXPOSE 3000 70 | 71 | # The default Rails Dockerfile uses `./bin/rails server`, but when using Puma, 72 | # they recommend using bundle exec puma. ref: https://github.com/puma/puma#rails 73 | CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"] 74 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 5 | 6 | ruby "3.4.2" 7 | 8 | # Bundle edge Rails instead: 9 | # gem "rails", github: "rails/rails", branch: "7-2-stable" 10 | gem "rails", "~> 7.2" 11 | 12 | # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] 13 | gem "sprockets-rails" 14 | 15 | # Use postgresql as the database for Active Record 16 | gem "pg", "~> 1.5" 17 | 18 | # Use the Puma web server [https://github.com/puma/puma] 19 | gem "puma", "~> 6.5" 20 | 21 | # Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] 22 | gem "importmap-rails" 23 | 24 | # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] 25 | gem "turbo-rails" 26 | 27 | # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] 28 | gem "stimulus-rails" 29 | 30 | # Build JSON APIs with ease [https://github.com/rails/jbuilder] 31 | gem "jbuilder" 32 | 33 | # Use Redis adapter to run Action Cable in production 34 | gem "redis", "~> 5.3" 35 | 36 | # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] 37 | # gem "kredis" 38 | 39 | # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] 40 | # gem "bcrypt", "~> 3.1.7" 41 | 42 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 43 | gem "tzinfo-data", platforms: %i[ windows jruby ] 44 | 45 | # Reduces boot times through caching; required in config/boot.rb 46 | gem "bootsnap", require: false 47 | 48 | # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] 49 | gem "image_processing", "~> 1.2" 50 | 51 | group :development, :test do 52 | # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem 53 | gem "debug", platforms: %i[ mri windows ], require: "debug/prelude" 54 | 55 | # Static analysis for security vulnerabilities [https://brakemanscanner.org/] 56 | gem "brakeman", require: false 57 | 58 | # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] 59 | gem "rubocop-rails-omakase", require: false 60 | 61 | gem "bundler-audit" 62 | gem "rspec-rails" 63 | gem "rubocop-rails" 64 | gem "rubocop-rspec" 65 | end 66 | 67 | group :development do 68 | # Use console on exceptions pages [https://github.com/rails/web-console] 69 | gem "web-console" 70 | 71 | # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] 72 | gem "rack-mini-profiler" 73 | end 74 | 75 | group :test do 76 | # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] 77 | gem "capybara" 78 | gem "selenium-webdriver" 79 | end 80 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actioncable (7.2.2.1) 5 | actionpack (= 7.2.2.1) 6 | activesupport (= 7.2.2.1) 7 | nio4r (~> 2.0) 8 | websocket-driver (>= 0.6.1) 9 | zeitwerk (~> 2.6) 10 | actionmailbox (7.2.2.1) 11 | actionpack (= 7.2.2.1) 12 | activejob (= 7.2.2.1) 13 | activerecord (= 7.2.2.1) 14 | activestorage (= 7.2.2.1) 15 | activesupport (= 7.2.2.1) 16 | mail (>= 2.8.0) 17 | actionmailer (7.2.2.1) 18 | actionpack (= 7.2.2.1) 19 | actionview (= 7.2.2.1) 20 | activejob (= 7.2.2.1) 21 | activesupport (= 7.2.2.1) 22 | mail (>= 2.8.0) 23 | rails-dom-testing (~> 2.2) 24 | actionpack (7.2.2.1) 25 | actionview (= 7.2.2.1) 26 | activesupport (= 7.2.2.1) 27 | nokogiri (>= 1.8.5) 28 | racc 29 | rack (>= 2.2.4, < 3.2) 30 | rack-session (>= 1.0.1) 31 | rack-test (>= 0.6.3) 32 | rails-dom-testing (~> 2.2) 33 | rails-html-sanitizer (~> 1.6) 34 | useragent (~> 0.16) 35 | actiontext (7.2.2.1) 36 | actionpack (= 7.2.2.1) 37 | activerecord (= 7.2.2.1) 38 | activestorage (= 7.2.2.1) 39 | activesupport (= 7.2.2.1) 40 | globalid (>= 0.6.0) 41 | nokogiri (>= 1.8.5) 42 | actionview (7.2.2.1) 43 | activesupport (= 7.2.2.1) 44 | builder (~> 3.1) 45 | erubi (~> 1.11) 46 | rails-dom-testing (~> 2.2) 47 | rails-html-sanitizer (~> 1.6) 48 | activejob (7.2.2.1) 49 | activesupport (= 7.2.2.1) 50 | globalid (>= 0.3.6) 51 | activemodel (7.2.2.1) 52 | activesupport (= 7.2.2.1) 53 | activerecord (7.2.2.1) 54 | activemodel (= 7.2.2.1) 55 | activesupport (= 7.2.2.1) 56 | timeout (>= 0.4.0) 57 | activestorage (7.2.2.1) 58 | actionpack (= 7.2.2.1) 59 | activejob (= 7.2.2.1) 60 | activerecord (= 7.2.2.1) 61 | activesupport (= 7.2.2.1) 62 | marcel (~> 1.0) 63 | activesupport (7.2.2.1) 64 | base64 65 | benchmark (>= 0.3) 66 | bigdecimal 67 | concurrent-ruby (~> 1.0, >= 1.3.1) 68 | connection_pool (>= 2.2.5) 69 | drb 70 | i18n (>= 1.6, < 2) 71 | logger (>= 1.4.2) 72 | minitest (>= 5.1) 73 | securerandom (>= 0.3) 74 | tzinfo (~> 2.0, >= 2.0.5) 75 | addressable (2.8.7) 76 | public_suffix (>= 2.0.2, < 7.0) 77 | ast (2.4.3) 78 | base64 (0.2.0) 79 | benchmark (0.4.0) 80 | bigdecimal (3.1.9) 81 | bindex (0.8.1) 82 | bootsnap (1.18.4) 83 | msgpack (~> 1.2) 84 | brakeman (7.0.2) 85 | racc 86 | builder (3.3.0) 87 | bundler-audit (0.9.2) 88 | bundler (>= 1.2.0, < 3) 89 | thor (~> 1.0) 90 | capybara (3.40.0) 91 | addressable 92 | matrix 93 | mini_mime (>= 0.1.3) 94 | nokogiri (~> 1.11) 95 | rack (>= 1.6.0) 96 | rack-test (>= 0.6.3) 97 | regexp_parser (>= 1.5, < 3.0) 98 | xpath (~> 3.2) 99 | concurrent-ruby (1.3.5) 100 | connection_pool (2.5.0) 101 | crass (1.0.6) 102 | date (3.4.1) 103 | debug (1.10.0) 104 | irb (~> 1.10) 105 | reline (>= 0.3.8) 106 | diff-lcs (1.6.0) 107 | drb (2.2.1) 108 | erubi (1.13.1) 109 | ffi (1.17.1-aarch64-linux-gnu) 110 | ffi (1.17.1-aarch64-linux-musl) 111 | ffi (1.17.1-arm-linux-gnu) 112 | ffi (1.17.1-arm-linux-musl) 113 | ffi (1.17.1-arm64-darwin) 114 | ffi (1.17.1-x86_64-darwin) 115 | ffi (1.17.1-x86_64-linux-gnu) 116 | ffi (1.17.1-x86_64-linux-musl) 117 | globalid (1.2.1) 118 | activesupport (>= 6.1) 119 | i18n (1.14.7) 120 | concurrent-ruby (~> 1.0) 121 | image_processing (1.14.0) 122 | mini_magick (>= 4.9.5, < 6) 123 | ruby-vips (>= 2.0.17, < 3) 124 | importmap-rails (2.1.0) 125 | actionpack (>= 6.0.0) 126 | activesupport (>= 6.0.0) 127 | railties (>= 6.0.0) 128 | io-console (0.8.0) 129 | irb (1.15.1) 130 | pp (>= 0.6.0) 131 | rdoc (>= 4.0.0) 132 | reline (>= 0.4.2) 133 | jbuilder (2.13.0) 134 | actionview (>= 5.0.0) 135 | activesupport (>= 5.0.0) 136 | json (2.10.2) 137 | language_server-protocol (3.17.0.4) 138 | lint_roller (1.1.0) 139 | logger (1.7.0) 140 | loofah (2.24.0) 141 | crass (~> 1.0.2) 142 | nokogiri (>= 1.12.0) 143 | mail (2.8.1) 144 | mini_mime (>= 0.1.1) 145 | net-imap 146 | net-pop 147 | net-smtp 148 | marcel (1.0.4) 149 | matrix (0.4.2) 150 | mini_magick (5.2.0) 151 | benchmark 152 | logger 153 | mini_mime (1.1.5) 154 | minitest (5.25.5) 155 | msgpack (1.8.0) 156 | net-imap (0.5.6) 157 | date 158 | net-protocol 159 | net-pop (0.1.2) 160 | net-protocol 161 | net-protocol (0.2.2) 162 | timeout 163 | net-smtp (0.5.1) 164 | net-protocol 165 | nio4r (2.7.4) 166 | nokogiri (1.18.4-aarch64-linux-gnu) 167 | racc (~> 1.4) 168 | nokogiri (1.18.4-aarch64-linux-musl) 169 | racc (~> 1.4) 170 | nokogiri (1.18.4-arm-linux-gnu) 171 | racc (~> 1.4) 172 | nokogiri (1.18.4-arm-linux-musl) 173 | racc (~> 1.4) 174 | nokogiri (1.18.4-arm64-darwin) 175 | racc (~> 1.4) 176 | nokogiri (1.18.4-x86_64-darwin) 177 | racc (~> 1.4) 178 | nokogiri (1.18.4-x86_64-linux-gnu) 179 | racc (~> 1.4) 180 | nokogiri (1.18.4-x86_64-linux-musl) 181 | racc (~> 1.4) 182 | parallel (1.26.3) 183 | parser (3.3.7.4) 184 | ast (~> 2.4.1) 185 | racc 186 | pg (1.5.9) 187 | pp (0.6.2) 188 | prettyprint 189 | prettyprint (0.2.0) 190 | prism (1.4.0) 191 | psych (5.2.3) 192 | date 193 | stringio 194 | public_suffix (6.0.1) 195 | puma (6.6.0) 196 | nio4r (~> 2.0) 197 | racc (1.8.1) 198 | rack (3.1.12) 199 | rack-mini-profiler (3.3.1) 200 | rack (>= 1.2.0) 201 | rack-session (2.1.0) 202 | base64 (>= 0.1.0) 203 | rack (>= 3.0.0) 204 | rack-test (2.2.0) 205 | rack (>= 1.3) 206 | rackup (2.2.1) 207 | rack (>= 3) 208 | rails (7.2.2.1) 209 | actioncable (= 7.2.2.1) 210 | actionmailbox (= 7.2.2.1) 211 | actionmailer (= 7.2.2.1) 212 | actionpack (= 7.2.2.1) 213 | actiontext (= 7.2.2.1) 214 | actionview (= 7.2.2.1) 215 | activejob (= 7.2.2.1) 216 | activemodel (= 7.2.2.1) 217 | activerecord (= 7.2.2.1) 218 | activestorage (= 7.2.2.1) 219 | activesupport (= 7.2.2.1) 220 | bundler (>= 1.15.0) 221 | railties (= 7.2.2.1) 222 | rails-dom-testing (2.2.0) 223 | activesupport (>= 5.0.0) 224 | minitest 225 | nokogiri (>= 1.6) 226 | rails-html-sanitizer (1.6.2) 227 | loofah (~> 2.21) 228 | nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) 229 | railties (7.2.2.1) 230 | actionpack (= 7.2.2.1) 231 | activesupport (= 7.2.2.1) 232 | irb (~> 1.13) 233 | rackup (>= 1.0.0) 234 | rake (>= 12.2) 235 | thor (~> 1.0, >= 1.2.2) 236 | zeitwerk (~> 2.6) 237 | rainbow (3.1.1) 238 | rake (13.2.1) 239 | rdoc (6.12.0) 240 | psych (>= 4.0.0) 241 | redis (5.4.0) 242 | redis-client (>= 0.22.0) 243 | redis-client (0.23.2) 244 | connection_pool 245 | regexp_parser (2.10.0) 246 | reline (0.6.0) 247 | io-console (~> 0.5) 248 | rexml (3.4.1) 249 | rspec-core (3.13.3) 250 | rspec-support (~> 3.13.0) 251 | rspec-expectations (3.13.3) 252 | diff-lcs (>= 1.2.0, < 2.0) 253 | rspec-support (~> 3.13.0) 254 | rspec-mocks (3.13.2) 255 | diff-lcs (>= 1.2.0, < 2.0) 256 | rspec-support (~> 3.13.0) 257 | rspec-rails (7.1.1) 258 | actionpack (>= 7.0) 259 | activesupport (>= 7.0) 260 | railties (>= 7.0) 261 | rspec-core (~> 3.13) 262 | rspec-expectations (~> 3.13) 263 | rspec-mocks (~> 3.13) 264 | rspec-support (~> 3.13) 265 | rspec-support (3.13.2) 266 | rubocop (1.75.1) 267 | json (~> 2.3) 268 | language_server-protocol (~> 3.17.0.2) 269 | lint_roller (~> 1.1.0) 270 | parallel (~> 1.10) 271 | parser (>= 3.3.0.2) 272 | rainbow (>= 2.2.2, < 4.0) 273 | regexp_parser (>= 2.9.3, < 3.0) 274 | rubocop-ast (>= 1.43.0, < 2.0) 275 | ruby-progressbar (~> 1.7) 276 | unicode-display_width (>= 2.4.0, < 4.0) 277 | rubocop-ast (1.43.0) 278 | parser (>= 3.3.7.2) 279 | prism (~> 1.4) 280 | rubocop-performance (1.24.0) 281 | lint_roller (~> 1.1) 282 | rubocop (>= 1.72.1, < 2.0) 283 | rubocop-ast (>= 1.38.0, < 2.0) 284 | rubocop-rails (2.31.0) 285 | activesupport (>= 4.2.0) 286 | lint_roller (~> 1.1) 287 | rack (>= 1.1) 288 | rubocop (>= 1.75.0, < 2.0) 289 | rubocop-ast (>= 1.38.0, < 2.0) 290 | rubocop-rails-omakase (1.1.0) 291 | rubocop (>= 1.72) 292 | rubocop-performance (>= 1.24) 293 | rubocop-rails (>= 2.30) 294 | rubocop-rspec (3.5.0) 295 | lint_roller (~> 1.1) 296 | rubocop (~> 1.72, >= 1.72.1) 297 | ruby-progressbar (1.13.0) 298 | ruby-vips (2.2.3) 299 | ffi (~> 1.12) 300 | logger 301 | rubyzip (2.4.1) 302 | securerandom (0.4.1) 303 | selenium-webdriver (4.31.0) 304 | base64 (~> 0.2) 305 | logger (~> 1.4) 306 | rexml (~> 3.2, >= 3.2.5) 307 | rubyzip (>= 1.2.2, < 3.0) 308 | websocket (~> 1.0) 309 | sprockets (4.2.1) 310 | concurrent-ruby (~> 1.0) 311 | rack (>= 2.2.4, < 4) 312 | sprockets-rails (3.5.2) 313 | actionpack (>= 6.1) 314 | activesupport (>= 6.1) 315 | sprockets (>= 3.0.0) 316 | stimulus-rails (1.3.4) 317 | railties (>= 6.0.0) 318 | stringio (3.1.5) 319 | thor (1.3.2) 320 | timeout (0.4.3) 321 | turbo-rails (2.0.13) 322 | actionpack (>= 7.1.0) 323 | railties (>= 7.1.0) 324 | tzinfo (2.0.6) 325 | concurrent-ruby (~> 1.0) 326 | unicode-display_width (3.1.4) 327 | unicode-emoji (~> 4.0, >= 4.0.4) 328 | unicode-emoji (4.0.4) 329 | useragent (0.16.11) 330 | web-console (4.2.1) 331 | actionview (>= 6.0.0) 332 | activemodel (>= 6.0.0) 333 | bindex (>= 0.4.0) 334 | railties (>= 6.0.0) 335 | websocket (1.2.11) 336 | websocket-driver (0.7.7) 337 | base64 338 | websocket-extensions (>= 0.1.0) 339 | websocket-extensions (0.1.5) 340 | xpath (3.2.0) 341 | nokogiri (~> 1.8) 342 | zeitwerk (2.7.2) 343 | 344 | PLATFORMS 345 | aarch64-linux-gnu 346 | aarch64-linux-musl 347 | arm-linux-gnu 348 | arm-linux-musl 349 | arm64-darwin 350 | x86_64-darwin 351 | x86_64-linux-gnu 352 | x86_64-linux-musl 353 | 354 | DEPENDENCIES 355 | bootsnap 356 | brakeman 357 | bundler-audit 358 | capybara 359 | debug 360 | image_processing (~> 1.2) 361 | importmap-rails 362 | jbuilder 363 | pg (~> 1.5) 364 | puma (~> 6.5) 365 | rack-mini-profiler 366 | rails (~> 7.2) 367 | redis (~> 5.3) 368 | rspec-rails 369 | rubocop-rails 370 | rubocop-rails-omakase 371 | rubocop-rspec 372 | selenium-webdriver 373 | sprockets-rails 374 | stimulus-rails 375 | turbo-rails 376 | tzinfo-data 377 | web-console 378 | 379 | RUBY VERSION 380 | ruby 3.4.2p28 381 | 382 | BUNDLED WITH 383 | 2.6.5 384 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec puma -C config/puma.rb 2 | -------------------------------------------------------------------------------- /Procfile.dev: -------------------------------------------------------------------------------- 1 | web: bin/rails server -p 3000 2 | css: bin/rails dartsass:watch 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/ryanwi/rails7-on-docker/actions/workflows/ci.yml/badge.svg)](https://github.com/ryanwi/rails7-on-docker/actions/workflows/ci.yml) 2 | [![Docker](https://github.com/ryanwi/rails7-on-docker/actions/workflows/docker.yml/badge.svg)](https://github.com/ryanwi/rails7-on-docker/actions/workflows/docker.yml) 3 | 4 | Start here: https://github.com/ryanwi/rails7-on-docker/generate 5 | 6 | # Rails 7 on Docker demo application 7 | 8 | This app demonstrates Rails 7 with PostgreSQL, import maps, turbo, stimulus and hotwire, all running in Docker. 9 | 10 | **NOTE:** There are also examples Rails 8 and Rails 6 applications working in Docker 11 | 12 | * [Rails 8 Applicaiton Docker Template](https://github.com/ryanwi/rails8-on-docker) 13 | * [Rails 7 Applicaiton Docker Template](https://github.com/ryanwi/rails7-on-docker) 14 | * [Rails 6 Application Docker Template](https://github.com/ryanwi/rails-on-docker) 15 | 16 | ## Features 17 | 18 | * Rails 7 19 | * Ruby 3.3 20 | * Dockerfile and Docker Compose configuration 21 | * PostgreSQL database 22 | * Redis 23 | * GitHub Actions for 24 | * tests 25 | * Rubocop for linting 26 | * Security checks with [Brakeman](https://github.com/presidentbeef/brakeman) and [bundler-audit](https://github.com/rubysec/bundler-audit) 27 | * Building and testing of a production Docker image 28 | * Dependabot for automated updates 29 | 30 | ## Requirements 31 | 32 | Please ensure you are using Docker Compose V2. This project relies on the `docker compose` command, not the previous `docker-compose` standalone program. 33 | 34 | https://docs.docker.com/compose/#compose-v2-and-the-new-docker-compose-command 35 | 36 | Check your docker compose version with: 37 | ``` 38 | % docker compose version 39 | Docker Compose version v2.10.2 40 | ``` 41 | 42 | ## Initial setup 43 | ``` 44 | cp .env.example .env 45 | docker compose build 46 | docker compose run --rm web bin/rails db:setup 47 | ``` 48 | 49 | ## Running the Rails app 50 | ``` 51 | docker compose up 52 | ``` 53 | 54 | ## Running the Rails console 55 | When the app is already running with `docker-compose` up, attach to the container: 56 | ``` 57 | docker compose exec web bin/rails c 58 | ``` 59 | 60 | When no container running yet, start up a new one: 61 | ``` 62 | docker compose run --rm web bin/rails c 63 | ``` 64 | 65 | ## Running tests 66 | ``` 67 | docker compose run --rm web bin/rspec 68 | ``` 69 | 70 | ## Updating gems 71 | ``` 72 | docker compose run --rm web bundle update 73 | docker compose up --build 74 | ``` 75 | 76 | ## Production build 77 | 78 | (adjust tags as needed) 79 | 80 | ### with [BuildKit](https://docs.docker.com/build/buildkit/) 81 | ``` 82 | DOCKER_BUILDKIT=1 docker build --tag rails-on-docker --load . 83 | ``` 84 | 85 | Test the image can be used and Rails starts up, use a fake key for testing purposes only: 86 | ``` 87 | docker run --rm --env SECRET_KEY_BASE=dummy rails-on-docker 88 | ``` 89 | 90 | ### With legacy builder (no BuildKit) 91 | ``` 92 | docker build --tag rails-on-docker . 93 | ``` 94 | 95 | Test the image can be used and Rails starts up, use a fake key for testing purposes only: 96 | ``` 97 | docker run --rm --env SECRET_KEY_BASE=dummy rails-on-docker 98 | ``` 99 | 100 | ## Deployment 101 | 102 | This app can be hosted wherever Ruby is supported and PostgreSQL databases can be provisioned. 103 | 104 | #### Render 105 | 106 | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/ryanwi/rails7-on-docker) 107 | 108 | NOTE: You will need to generate a production secret with `bin/rails secret` and set it as the `SECRET_KEY_BASE` environment variable. 109 | 110 | ## Credits/References 111 | 112 | ### Rails with Docker 113 | * [Quickstart: Compose and Rails](https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/rails/) 114 | * [Docker Rails Samples](https://docs.docker.com/samples/rails/) 115 | * [Docker for Rails Developers 116 | Build, Ship, and Run Your Applications Everywhere](https://pragprog.com/titles/ridocker/docker-for-rails-developers/) 117 | * [Ruby on Whales: 118 | Dockerizing Ruby and Rails development](https://evilmartians.com/chronicles/ruby-on-whales-docker-for-ruby-rails-development) 119 | * [Rails generator to produce Dockerfiles and related files](https://github.com/rubys/dockerfile-rails) 120 | * [docker init](https://docs.docker.com/engine/reference/commandline/init/) 121 | * [Rails 7.1 Dockerfile Generator Template](https://github.com/rails/rails/blob/main/railties/lib/rails/generators/rails/app/templates/Dockerfile.tt) 122 | 123 | ### Rails 7 with importmaps 124 | 125 | * [Alpha preview: Modern JavaScript in Rails 7 without Webpack](https://www.youtube.com/watch?v=PtxZvFnL2i0) 126 | 127 | ### Rails 7 with hotwire 128 | 129 | * [Stimulus 3 + Turbo 7 = Hotwire 1.0](https://world.hey.com/dhh/stimulus-3-turbo-7-hotwire-1-0-9d507133) 130 | * [Turbo 7](https://world.hey.com/hotwired/turbo-7-0dd7a27f) 131 | * [Rails 7 will have three great answers to JavaScript in 2021+](https://world.hey.com/dhh/rails-7-will-have-three-great-answers-to-javascript-in-2021-8d68191b) 132 | * [Hotwire Turbo Replacing Rails UJS](https://www.driftingruby.com/episodes/hotwire-turbo-replacing-rails-ujs) 133 | 134 | ## Author 135 | 136 | **Ryan Williams** 137 | 138 | - 139 | - 140 | - 141 | - 142 | -------------------------------------------------------------------------------- /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 ../stylesheets .css 3 | //= link_tree ../../javascript .js 4 | //= link_tree ../../../vendor/javascript .js 5 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/stylesheets/actiontext.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and 3 | * the trix-editor content (whether displayed or under editing). Feel free to incorporate this 4 | * inclusion directly in any other asset bundle and remove this file. 5 | * 6 | *= require trix 7 | */ 8 | 9 | /* 10 | * We need to override trix.css’s image gallery styles to accommodate the 11 | * element we wrap around attachments. Otherwise, 12 | * images in galleries will be squished by the max-width: 33%; rule. 13 | */ 14 | .trix-content .attachment-gallery > action-text-attachment, 15 | .trix-content .attachment-gallery > .attachment { 16 | flex: 1 0 33%; 17 | padding: 0 0.5em; 18 | max-width: 33%; 19 | } 20 | 21 | .trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment, 22 | .trix-content .attachment-gallery.attachment-gallery--2 > .attachment, .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment, 23 | .trix-content .attachment-gallery.attachment-gallery--4 > .attachment { 24 | flex-basis: 50%; 25 | max-width: 50%; 26 | } 27 | 28 | .trix-content action-text-attachment .attachment { 29 | padding: 0 !important; 30 | max-width: 100% !important; 31 | } 32 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /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 | end 5 | -------------------------------------------------------------------------------- /app/controllers/articles_controller.rb: -------------------------------------------------------------------------------- 1 | class ArticlesController < ApplicationController 2 | before_action :set_article, only: %i[ show edit update destroy ] 3 | 4 | # GET /articles or /articles.json 5 | def index 6 | @articles = Article.all 7 | end 8 | 9 | # GET /articles/1 or /articles/1.json 10 | def show 11 | end 12 | 13 | # GET /articles/new 14 | def new 15 | @article = Article.new 16 | end 17 | 18 | # GET /articles/1/edit 19 | def edit 20 | end 21 | 22 | # POST /articles or /articles.json 23 | def create 24 | @article = Article.new(article_params) 25 | 26 | respond_to do |format| 27 | if @article.save 28 | format.html { redirect_to @article, notice: "Article was successfully created." } 29 | format.json { render :show, status: :created, location: @article } 30 | else 31 | format.html { render :new, status: :unprocessable_entity } 32 | format.json { render json: @article.errors, status: :unprocessable_entity } 33 | end 34 | end 35 | end 36 | 37 | # PATCH/PUT /articles/1 or /articles/1.json 38 | def update 39 | respond_to do |format| 40 | if @article.update(article_params) 41 | format.html { redirect_to @article, notice: "Article was successfully updated." } 42 | format.json { render :show, status: :ok, location: @article } 43 | else 44 | format.html { render :edit, status: :unprocessable_entity } 45 | format.json { render json: @article.errors, status: :unprocessable_entity } 46 | end 47 | end 48 | end 49 | 50 | # DELETE /articles/1 or /articles/1.json 51 | def destroy 52 | @article.destroy 53 | respond_to do |format| 54 | format.html { redirect_to articles_url, notice: "Article was successfully destroyed." } 55 | format.json { head :no_content } 56 | end 57 | end 58 | 59 | private 60 | # Use callbacks to share common setup or constraints between actions. 61 | def set_article 62 | @article = Article.find(params[:id]) 63 | end 64 | 65 | # Only allow a list of trusted parameters through. 66 | def article_params 67 | params.require(:article).permit(:title, :content) 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /app/controllers/comments_controller.rb: -------------------------------------------------------------------------------- 1 | class CommentsController < ApplicationController 2 | before_action :set_article 3 | 4 | def create 5 | @article.comments.create! params.required(:comment).permit(:content) 6 | redirect_to @article 7 | end 8 | 9 | private 10 | def set_article 11 | @article = Article.find(params[:article_id]) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/welcome_controller.rb: -------------------------------------------------------------------------------- 1 | class WelcomeController < ApplicationController 2 | def index 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | end 5 | -------------------------------------------------------------------------------- /app/helpers/articles_helper.rb: -------------------------------------------------------------------------------- 1 | module ArticlesHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/comments_helper.rb: -------------------------------------------------------------------------------- 1 | module CommentsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/welcome_helper.rb: -------------------------------------------------------------------------------- 1 | module WelcomeHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/javascript/application.js: -------------------------------------------------------------------------------- 1 | // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails 2 | import "@hotwired/turbo-rails" 3 | import "controllers" 4 | import "trix" 5 | import "@rails/actiontext" 6 | 7 | console.log('Hello World from application.js'); 8 | -------------------------------------------------------------------------------- /app/javascript/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus" 2 | 3 | const application = Application.start() 4 | 5 | // Configure Stimulus development experience 6 | application.debug = false 7 | window.Stimulus = application 8 | 9 | export { application } 10 | 11 | console.log('Hello World from controllers/application.js'); 12 | -------------------------------------------------------------------------------- /app/javascript/controllers/hello_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | static targets = [ "name", "output" ] 5 | 6 | connect() { 7 | // this.element.textContent = "Hello World!" 8 | console.log('Hello World hello_controller.js'); 9 | } 10 | 11 | greet() { 12 | console.log('greet'); 13 | this.outputTarget.textContent = 14 | `Hello, ${this.nameTarget.value}!` 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/javascript/controllers/index.js: -------------------------------------------------------------------------------- 1 | // Import and register all your controllers from the importmap under controllers/* 2 | 3 | import { application } from "controllers/application" 4 | 5 | // Eager load all controllers defined in the import map under controllers/**/*_controller 6 | import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" 7 | eagerLoadControllersFrom("controllers", application) 8 | 9 | // Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!) 10 | // import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading" 11 | // lazyLoadControllersFrom("controllers", application) 12 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationJob < ActiveJob::Base 4 | # Automatically retry jobs that encountered a deadlock 5 | # retry_on ActiveRecord::Deadlocked 6 | 7 | # Most jobs are safe to ignore if the underlying records are no longer available 8 | # discard_on ActiveJob::DeserializationError 9 | end 10 | -------------------------------------------------------------------------------- /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/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | primary_abstract_class 5 | end 6 | -------------------------------------------------------------------------------- /app/models/article.rb: -------------------------------------------------------------------------------- 1 | class Article < ApplicationRecord 2 | has_many :comments, dependent: :destroy 3 | has_rich_text :content 4 | validates_presence_of :title 5 | end 6 | -------------------------------------------------------------------------------- /app/models/comment.rb: -------------------------------------------------------------------------------- 1 | class Comment < ApplicationRecord 2 | belongs_to :article 3 | broadcasts_to :article 4 | end 5 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/views/active_storage/blobs/_blob.html.erb: -------------------------------------------------------------------------------- 1 |
attachment--<%= blob.filename.extension %>"> 2 | <% if blob.representable? %> 3 | <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %> 4 | <% end %> 5 | 6 |
7 | <% if caption = blob.try(:caption) %> 8 | <%= caption %> 9 | <% else %> 10 | <%= blob.filename %> 11 | <%= number_to_human_size blob.byte_size %> 12 | <% end %> 13 |
14 |
15 | -------------------------------------------------------------------------------- /app/views/articles/_article.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

3 | Title: 4 | <%= article.title %> 5 |

6 | 7 |

8 | Posted <%= time_tag article.created_at %> 9 |

10 | 11 |

12 | <%= pluralize article.comments.count, "comment" %> 13 |

14 | 15 |

16 | Content: 17 | <%= article.content %> 18 |

19 | 20 |

21 | <%= link_to "Show this article", article %> 22 |

23 |
24 | -------------------------------------------------------------------------------- /app/views/articles/_article.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.extract! article, :id, :title, :content, :created_at, :updated_at 2 | json.url article_url(article, format: :json) 3 | -------------------------------------------------------------------------------- /app/views/articles/_comments.html.erb: -------------------------------------------------------------------------------- 1 |

Comments

2 | 3 |
4 | <%= render article.comments %> 5 |
6 | 7 | <%= render "comments/new", article: article %> 8 | -------------------------------------------------------------------------------- /app/views/articles/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_with(model: article) do |form| %> 2 | <% if article.errors.any? %> 3 |
4 |

<%= pluralize(article.errors.count, "error") %> prohibited this article from being saved:

5 | 6 |
    7 | <% article.errors.each do |error| %> 8 |
  • <%= error.full_message %>
  • 9 | <% end %> 10 |
11 |
12 | <% end %> 13 | 14 |
15 | <%= form.label :title %> 16 | <%= form.text_field :title %> 17 |
18 | 19 |
20 | <%= form.label :content %> 21 | <%= form.rich_text_area :content %> 22 |
23 | 24 |
25 | <%= form.submit %> 26 |
27 | <% end %> 28 | -------------------------------------------------------------------------------- /app/views/articles/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing article

2 | 3 | <%= render "form", article: @article %> 4 | 5 |
6 | 7 |
8 | <%= link_to "Show this article", @article %> | 9 | <%= link_to "Back to articles", articles_path %> 10 |
11 | -------------------------------------------------------------------------------- /app/views/articles/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

Article

4 | 5 |
6 | <%= render @articles %> 7 |
8 | 9 | <%= link_to "New article", new_article_path %> 10 | -------------------------------------------------------------------------------- /app/views/articles/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.array! @articles, partial: "articles/article", as: :article 2 | -------------------------------------------------------------------------------- /app/views/articles/new.html.erb: -------------------------------------------------------------------------------- 1 |

New article

2 | 3 | <%= render "form", article: @article %> 4 | 5 |
6 | 7 |
8 | <%= link_to "Back to articles", articles_path %> 9 |
10 | -------------------------------------------------------------------------------- /app/views/articles/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream_from @article %> 2 | 3 |

<%= notice %>

4 | 5 | <%= render @article %> 6 | <%= render "articles/comments", article: @article %> 7 | 8 |
9 | <%= link_to "Edit this article", edit_article_path(@article) %> | 10 | <%= link_to "Back to articles", articles_path %> 11 | 12 | <%= button_to "Destroy this article", article_path(@article), method: :delete %> 13 |
14 | -------------------------------------------------------------------------------- /app/views/articles/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.partial! "articles/article", article: @article 2 | -------------------------------------------------------------------------------- /app/views/comments/_comment.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= comment.content %> 3 | - <%= time_tag comment.created_at %> 4 |
5 | -------------------------------------------------------------------------------- /app/views/comments/_new.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_with model: [ article, Comment.new ] do |form| %> 2 | Your comment:
3 | <%= form.text_area :content, size: "20x5" %> 4 | <%= form.submit %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/layouts/action_text/contents/_content.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= yield -%> 3 |
4 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Railsondocker 5 | 6 | <%= csrf_meta_tags %> 7 | <%= csp_meta_tag %> 8 | 9 | <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> 10 | <%= javascript_importmap_tags %> 11 | 12 | 13 | 14 | 15 | <%= yield %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/views/welcome/index.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome

2 | 3 | <%= link_to "Articles", articles_path %> 4 | 5 | 6 |

Stimulus Check

7 | 8 |
9 | 10 | 11 | 14 | 15 | 16 | 17 |
18 | -------------------------------------------------------------------------------- /bin/brakeman: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | ARGV.unshift("--ensure-latest") 6 | 7 | load Gem.bin_path("brakeman", "brakeman") 8 | -------------------------------------------------------------------------------- /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 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", __dir__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, ".locked") 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_requirement 64 | @bundler_requirement ||= 65 | env_var_version || 66 | cli_arg_version || 67 | bundler_requirement_for(lockfile_version) 68 | end 69 | 70 | def bundler_requirement_for(version) 71 | return "#{Gem::Requirement.default}.a" unless version 72 | 73 | bundler_gem_version = Gem::Version.new(version) 74 | 75 | bundler_gem_version.approximate_recommendation 76 | end 77 | 78 | def load_bundler! 79 | ENV["BUNDLE_GEMFILE"] ||= gemfile 80 | 81 | activate_bundler 82 | end 83 | 84 | def activate_bundler 85 | gem_error = activation_error_handling do 86 | gem "bundler", bundler_requirement 87 | end 88 | return if gem_error.nil? 89 | require_error = activation_error_handling do 90 | require "bundler/version" 91 | end 92 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 93 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 94 | exit 42 95 | end 96 | 97 | def activation_error_handling 98 | yield 99 | nil 100 | rescue StandardError, LoadError => e 101 | e 102 | end 103 | end 104 | 105 | m.load_bundler! 106 | 107 | if m.invoked_as_script? 108 | load Gem.bin_path("bundler", "bundle") 109 | end 110 | -------------------------------------------------------------------------------- /bin/docker-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # Enable jemalloc for reduced memory usage and latency. 4 | if [ -z "${LD_PRELOAD+x}" ] && [ -f /usr/lib/*/libjemalloc.so.2 ]; then 5 | export LD_PRELOAD="$(echo /usr/lib/*/libjemalloc.so.2)" 6 | fi 7 | 8 | # NOTE: Enable this as you need to get migrations working in your deployed 9 | # (i.e. Production) environments. Match the condition check to what you have in 10 | # the Dockerfile CMD. I use puma in the production.Dockerfile as that's the 11 | # recommended option by the Puma team (https://github.com/puma/puma#rails), but 12 | # the default Rails Dockerfile uses `./bin/rails server` 13 | 14 | # echo "${1}" 15 | # echo "${2}" 16 | # echo "${3}" 17 | 18 | # # If running the rails server then create or migrate existing database 19 | # if [ "${1}" == "bundle" ] && [ "${2}" == "exec" ] && [ "${3}" == "puma" ]; then 20 | # ./bin/rails db:prepare 21 | # fi 22 | 23 | exec "${@}" 24 | -------------------------------------------------------------------------------- /bin/docker-entrypoint-development: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Remove a potentially pre-existing server.pid for Rails. 5 | rm -f /usr/src/app/tmp/pids/server.pid 6 | 7 | echo "bundle install..." 8 | bundle check || bundle install --jobs 4 9 | 10 | # Then exec the container's main process (what's set as CMD in the Dockerfile). 11 | exec "$@" 12 | -------------------------------------------------------------------------------- /bin/importmap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require_relative "../config/application" 4 | require "importmap/commands" 5 | -------------------------------------------------------------------------------- /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', __dir__) 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 | require "rubygems" 3 | require "bundler/setup" 4 | 5 | # explicit rubocop config increases performance slightly while avoiding config confusion. 6 | ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) 7 | 8 | load Gem.bin_path("rubocop", "rubocop") 9 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | APP_ROOT = File.expand_path("..", __dir__) 5 | APP_NAME = "railsondocker" 6 | 7 | def system!(*args) 8 | system(*args, exception: true) 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time 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 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?("config/database.yml") 22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml" 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! "bin/rails db:prepare" 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! "bin/rails log:clear tmp:clear" 30 | 31 | puts "\n== Restarting application server ==" 32 | system! "bin/rails restart" 33 | 34 | # puts "\n== Configuring puma-dev ==" 35 | # system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}" 36 | # system "curl -Is https://#{APP_NAME}.test/up | head -n 1" 37 | end 38 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: 4 | context: ./ 5 | dockerfile: development.Dockerfile 6 | command: bash -c "rm -f tmp/pids/server.pid && bin/rails s -p 3000 -b '0.0.0.0'" 7 | volumes: 8 | - .:/usr/src/app 9 | - bundle:/usr/local/bundle 10 | ports: 11 | - "3000:3000" 12 | env_file: 13 | - .env 14 | environment: 15 | - HISTFILE=/usr/src/app/log/.bash_history 16 | depends_on: 17 | db: 18 | condition: service_healthy 19 | redis: 20 | condition: service_started 21 | db: 22 | image: postgres:17 23 | ports: 24 | - "5432:5432" 25 | environment: 26 | - POSTGRES_PASSWORD=changeme 27 | volumes: 28 | - pg_data:/var/lib/postgresql/data 29 | healthcheck: 30 | test: pg_isready -U postgres 31 | interval: 2s 32 | timeout: 5s 33 | retries: 30 34 | redis: 35 | image: redis 36 | volumes: 37 | - redis_data:/data 38 | 39 | volumes: 40 | pg_data: 41 | redis_data: 42 | bundle: 43 | -------------------------------------------------------------------------------- /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 | Rails.application.load_server 9 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "active_storage/engine" 9 | require "action_controller/railtie" 10 | require "action_mailer/railtie" 11 | # require "action_mailbox/engine" 12 | require "action_text/engine" 13 | require "action_view/railtie" 14 | require "action_cable/engine" 15 | # require "rails/test_unit/railtie" 16 | 17 | # Require the gems listed in Gemfile, including any gems 18 | # you've limited to :test, :development, or :production. 19 | Bundler.require(*Rails.groups) 20 | 21 | module Railsondocker 22 | class Application < Rails::Application 23 | # Initialize configuration defaults for originally generated Rails version. 24 | config.load_defaults 7.2 25 | 26 | # Please, add to the `ignore` list any other `lib` subdirectories that do 27 | # not contain `.rb` files, or that should not be reloaded or eager loaded. 28 | # Common ones are `templates`, `generators`, or `middleware`, for example. 29 | config.autoload_lib(ignore: %w[assets tasks]) 30 | 31 | # Configuration for the application, engines, and railties goes here. 32 | # 33 | # These settings can be overridden in specific environments using the files 34 | # in config/environments, which are processed later. 35 | # 36 | # config.time_zone = "Central Time (US & Canada)" 37 | # config.eager_load_paths << Rails.root.join("extras") 38 | 39 | # Don't generate system test files. 40 | config.generators.system_tests = nil 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 2 | 3 | require "bundler/setup" # Set up gems listed in the Gemfile. 4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: redis 3 | url: redis://redis:6379/1 4 | 5 | test: 6 | adapter: test 7 | 8 | production: 9 | adapter: redis 10 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 11 | channel_prefix: railsondocker_production 12 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 9.3 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On macOS with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On Windows: 8 | # gem install pg 9 | # Choose the win32 build. 10 | # Install PostgreSQL and put its /bin directory on your path. 11 | # 12 | # Configure Using Gemfile 13 | # gem "pg" 14 | # 15 | default: &default 16 | adapter: postgresql 17 | encoding: unicode 18 | # For details on connection pooling, see Rails configuration guide 19 | # https://guides.rubyonrails.org/configuring.html#database-pooling 20 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 21 | 22 | 23 | development: 24 | <<: *default 25 | database: railsondocker_development 26 | 27 | # The specified database role being used to connect to PostgreSQL. 28 | # To create additional roles in PostgreSQL see `$ createuser --help`. 29 | # When left blank, PostgreSQL will use the default role. This is 30 | # the same name as the operating system user running Rails. 31 | #username: railsondocker72pg 32 | 33 | # The password associated with the PostgreSQL role (username). 34 | #password: 35 | 36 | # Connect on a TCP socket. Omitted by default since the client uses a 37 | # domain socket that doesn't need configuration. Windows does not have 38 | # domain sockets, so uncomment these lines. 39 | #host: localhost 40 | 41 | # The TCP port the server listens on. Defaults to 5432. 42 | # If your server runs on a different port number, change accordingly. 43 | #port: 5432 44 | 45 | # Schema search path. The server defaults to $user,public 46 | #schema_search_path: myapp,sharedapp,public 47 | 48 | # Minimum log levels, in increasing order: 49 | # debug5, debug4, debug3, debug2, debug1, 50 | # log, notice, warning, error, fatal, and panic 51 | # Defaults to warning. 52 | #min_messages: notice 53 | 54 | # Warning: The database defined as "test" will be erased and 55 | # re-generated from your development database when you run "rake". 56 | # Do not set this db to the same as development or production. 57 | test: 58 | <<: *default 59 | database: railsondocker_test 60 | 61 | # As with config/credentials.yml, you never want to store sensitive information, 62 | # like your database password, in your source code. If your source code is 63 | # ever seen by anyone, they now have access to your database. 64 | # 65 | # Instead, provide the password or a full connection URL as an environment 66 | # variable when you boot the app. For example: 67 | # 68 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" 69 | # 70 | # If the connection URL is provided in the special DATABASE_URL environment 71 | # variable, Rails will automatically merge its configuration values on top of 72 | # the values provided in this file. Alternatively, you can specify a connection 73 | # URL environment variable explicitly: 74 | # 75 | # production: 76 | # url: <%= ENV["MY_APP_DATABASE_URL"] %> 77 | # 78 | # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database 79 | # for a full overview on how database connection configuration can be specified. 80 | # 81 | production: 82 | <<: *default 83 | url: <%= ENV['DATABASE_URL'] %> 84 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # In the development environment your application's code is reloaded any time 7 | # it changes. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.enable_reloading = true 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports. 15 | config.consider_all_requests_local = true 16 | 17 | # Allow access when running in docker 18 | config.web_console.allowed_ips = [ "172.16.0.0/12", "192.168.0.0/16" ] 19 | 20 | # Enable server timing. 21 | config.server_timing = true 22 | 23 | # Enable/disable caching. By default caching is disabled. 24 | # Run rails dev:cache to toggle caching. 25 | if Rails.root.join("tmp/caching-dev.txt").exist? 26 | config.action_controller.perform_caching = true 27 | config.action_controller.enable_fragment_cache_logging = true 28 | 29 | config.cache_store = :memory_store 30 | config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" } 31 | else 32 | config.action_controller.perform_caching = false 33 | 34 | config.cache_store = :null_store 35 | end 36 | 37 | # Store uploaded files on the local file system (see config/storage.yml for options). 38 | config.active_storage.service = :local 39 | 40 | # Don't care if the mailer can't send. 41 | config.action_mailer.raise_delivery_errors = false 42 | 43 | # Disable caching for Action Mailer templates even if Action Controller 44 | # caching is enabled. 45 | config.action_mailer.perform_caching = false 46 | 47 | config.action_mailer.default_url_options = { host: "localhost", port: 3000 } 48 | 49 | # Print deprecation notices to the Rails logger. 50 | config.active_support.deprecation = :log 51 | 52 | # Raise exceptions for disallowed deprecations. 53 | config.active_support.disallowed_deprecation = :raise 54 | 55 | # Tell Active Support which deprecation messages to disallow. 56 | config.active_support.disallowed_deprecation_warnings = [] 57 | 58 | # Raise an error on page load if there are pending migrations. 59 | config.active_record.migration_error = :page_load 60 | 61 | # Highlight code that triggered database queries in logs. 62 | config.active_record.verbose_query_logs = true 63 | 64 | # Highlight code that enqueued background job in logs. 65 | config.active_job.verbose_enqueue_logs = true 66 | 67 | # Suppress logger output for asset requests. 68 | config.assets.quiet = true 69 | 70 | # Raises error for missing translations. 71 | # config.i18n.raise_on_missing_translations = true 72 | 73 | # Annotate rendered view with file names. 74 | config.action_view.annotate_rendered_view_with_filenames = true 75 | 76 | # Uncomment if you wish to allow Action Cable access from any origin. 77 | # config.action_cable.disable_request_forgery_protection = true 78 | 79 | # Raise error when a before_action's only/except options reference missing actions. 80 | config.action_controller.raise_on_missing_callback_actions = true 81 | 82 | # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. 83 | # config.generators.apply_rubocop_autocorrect_after_generate! 84 | end 85 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.enable_reloading = false 8 | 9 | # Eager load code on boot. This eager loads most of Rails and 10 | # your application in memory, allowing both threaded web servers 11 | # and those relying on copy on write to perform better. 12 | # Rake tasks automatically ignore this option for performance. 13 | config.eager_load = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment 20 | # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). 21 | # config.require_master_key = true 22 | 23 | # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. 24 | # config.public_file_server.enabled = false 25 | 26 | # Compress CSS using a preprocessor. 27 | # config.assets.css_compressor = :sass 28 | 29 | # Do not fall back to assets pipeline if a precompiled asset is missed. 30 | config.assets.compile = false 31 | 32 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 33 | # config.asset_host = "http://assets.example.com" 34 | 35 | # Specifies the header that your server uses for sending files. 36 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache 37 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX 38 | 39 | # Store uploaded files on the local file system (see config/storage.yml for options). 40 | config.active_storage.service = :local 41 | 42 | # Mount Action Cable outside main process or domain. 43 | # config.action_cable.mount_path = nil 44 | # config.action_cable.url = "wss://example.com/cable" 45 | # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] 46 | 47 | # Assume all access to the app is happening through a SSL-terminating reverse proxy. 48 | # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. 49 | # config.assume_ssl = true 50 | 51 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 52 | config.force_ssl = true 53 | 54 | # Skip http-to-https redirect for the default health check endpoint. 55 | # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } 56 | 57 | # Log to STDOUT by default 58 | config.logger = ActiveSupport::Logger.new(STDOUT) 59 | .tap { |logger| logger.formatter = ::Logger::Formatter.new } 60 | .then { |logger| ActiveSupport::TaggedLogging.new(logger) } 61 | 62 | # Prepend all log lines with the following tags. 63 | config.log_tags = [ :request_id ] 64 | 65 | # "info" includes generic and useful information about system operation, but avoids logging too much 66 | # information to avoid inadvertent exposure of personally identifiable information (PII). If you 67 | # want to log everything, set the level to "debug". 68 | config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") 69 | 70 | # Use a different cache store in production. 71 | # config.cache_store = :mem_cache_store 72 | 73 | # Use a real queuing backend for Active Job (and separate queues per environment). 74 | # config.active_job.queue_adapter = :resque 75 | # config.active_job.queue_name_prefix = "railsondocker_production" 76 | 77 | # Disable caching for Action Mailer templates even if Action Controller 78 | # caching is enabled. 79 | config.action_mailer.perform_caching = false 80 | 81 | # Ignore bad email addresses and do not raise email delivery errors. 82 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 83 | # config.action_mailer.raise_delivery_errors = false 84 | 85 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 86 | # the I18n.default_locale when a translation cannot be found). 87 | config.i18n.fallbacks = true 88 | 89 | # Don't log any deprecations. 90 | config.active_support.report_deprecations = false 91 | 92 | # Do not dump schema after migrations. 93 | config.active_record.dump_schema_after_migration = false 94 | 95 | # Enable DNS rebinding protection and other `Host` header attacks. 96 | # config.hosts = [ 97 | # "example.com", # Allow requests from example.com 98 | # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` 99 | # ] 100 | # Skip DNS rebinding protection for the default health check endpoint. 101 | # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } 102 | end 103 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | 8 | Rails.application.configure do 9 | # Settings specified here will take precedence over those in config/application.rb. 10 | 11 | # While tests run files are not watched, reloading is not necessary. 12 | config.enable_reloading = false 13 | 14 | # Eager loading loads your entire application. When running a single test locally, 15 | # this is usually not necessary, and can slow down your test suite. However, it's 16 | # recommended that you enable it in continuous integration systems to ensure eager 17 | # loading is working properly 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.headers = { "Cache-Control" => "public, max-age=#{1.hour.to_i}" } 22 | 23 | # Show full error reports and disable caching. 24 | config.consider_all_requests_local = true 25 | config.action_controller.perform_caching = false 26 | config.cache_store = :null_store 27 | 28 | # Render exception templates for rescuable exceptions and raise for other exceptions. 29 | config.action_dispatch.show_exceptions = :rescuable 30 | 31 | # Disable request forgery protection in test environment. 32 | config.action_controller.allow_forgery_protection = false 33 | 34 | # Store uploaded files on the local file system in a temporary directory. 35 | config.active_storage.service = :test 36 | 37 | # Disable caching for Action Mailer templates even if Action Controller 38 | # caching is enabled. 39 | config.action_mailer.perform_caching = false 40 | 41 | # Tell Action Mailer not to deliver emails to the real world. 42 | # The :test delivery method accumulates sent emails in the 43 | # ActionMailer::Base.deliveries array. 44 | config.action_mailer.delivery_method = :test 45 | 46 | # Unlike controllers, the mailer instance doesn't have any context about the 47 | # incoming request so you'll need to provide the :host parameter yourself. 48 | config.action_mailer.default_url_options = { host: "www.example.com" } 49 | 50 | # Print deprecation notices to the stderr. 51 | config.active_support.deprecation = :stderr 52 | 53 | # Raise exceptions for disallowed deprecations. 54 | config.active_support.disallowed_deprecation = :raise 55 | 56 | # Tell Active Support which deprecation messages to disallow. 57 | config.active_support.disallowed_deprecation_warnings = [] 58 | 59 | # Raises error for missing translations. 60 | # config.i18n.raise_on_missing_translations = true 61 | 62 | # Annotate rendered view with file names. 63 | # config.action_view.annotate_rendered_view_with_filenames = true 64 | 65 | # Raise error when a before_action's only/except options reference missing actions. 66 | config.action_controller.raise_on_missing_callback_actions = true 67 | end 68 | -------------------------------------------------------------------------------- /config/importmap.rb: -------------------------------------------------------------------------------- 1 | # Pin npm packages by running ./bin/importmap 2 | 3 | pin "application", preload: true 4 | pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true 5 | pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true 6 | pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true 7 | pin_all_from "app/javascript/controllers", under: "controllers" 8 | 9 | pin "trix" 10 | pin "@rails/actiontext", to: "actiontext.js" 11 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = "1.0" 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | -------------------------------------------------------------------------------- /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| /my_noisy_library/.match?(line) } 7 | 8 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code 9 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". 10 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] 11 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy. 4 | # See the Securing Rails Applications Guide for more information: 5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header 6 | 7 | # Rails.application.configure do 8 | # config.content_security_policy do |policy| 9 | # policy.default_src :self, :https 10 | # policy.font_src :self, :https, :data 11 | # policy.img_src :self, :https, :data 12 | # policy.object_src :none 13 | # policy.script_src :self, :https 14 | # policy.style_src :self, :https 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | # 19 | # # Generate session nonces for permitted importmap, inline scripts, and inline styles. 20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 21 | # config.content_security_policy_nonce_directives = %w(script-src style-src) 22 | # 23 | # # Report violations without enforcing the policy. 24 | # # config.content_security_policy_report_only = true 25 | # end 26 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. 4 | # Use this to limit dissemination of sensitive information. 5 | # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. 6 | Rails.application.config.filter_parameters += [ 7 | :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 8 | ] 9 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, "\\1en" 8 | # inflect.singular /^(ox)en/i, "\\1" 9 | # inflect.irregular "person", "people" 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym "RESTful" 16 | # end 17 | -------------------------------------------------------------------------------- /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/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide HTTP permissions policy. For further 4 | # information see: https://developers.google.com/web/updates/2018/06/feature-policy 5 | 6 | # Rails.application.config.permissions_policy do |policy| 7 | # policy.camera :none 8 | # policy.gyroscope :none 9 | # policy.microphone :none 10 | # policy.usb :none 11 | # policy.fullscreen :self 12 | # policy.payment :self, "https://secure.example.com" 13 | # end 14 | -------------------------------------------------------------------------------- /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/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization and 2 | # are automatically loaded by Rails. If you want to use locales other than 3 | # 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 | # To learn more about the API, please read the Rails Internationalization guide 20 | # at https://guides.rubyonrails.org/i18n.html. 21 | # 22 | # Be aware that YAML interprets the following case-insensitive strings as 23 | # booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings 24 | # must be quoted to be interpreted as strings. For example: 25 | # 26 | # en: 27 | # "yes": yup 28 | # enabled: "ON" 29 | 30 | en: 31 | hello: "Hello world" 32 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # This configuration file will be evaluated by Puma. The top-level methods that 2 | # are invoked here are part of Puma's configuration DSL. For more information 3 | # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. 4 | 5 | # Puma starts a configurable number of processes (workers) and each process 6 | # serves each request in a thread from an internal thread pool. 7 | # 8 | # The ideal number of threads per worker depends both on how much time the 9 | # application spends waiting for IO operations and on how much you wish to 10 | # to prioritize throughput over latency. 11 | # 12 | # As a rule of thumb, increasing the number of threads will increase how much 13 | # traffic a given process can handle (throughput), but due to CRuby's 14 | # Global VM Lock (GVL) it has diminishing returns and will degrade the 15 | # response time (latency) of the application. 16 | # 17 | # The default is set to 3 threads as it's deemed a decent compromise between 18 | # throughput and latency for the average Rails application. 19 | # 20 | # Any libraries that use a connection pool or another resource pool should 21 | # be configured to provide at least as many connections as the number of 22 | # threads. This includes Active Record's `pool` parameter in `database.yml`. 23 | threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) 24 | threads threads_count, threads_count 25 | 26 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 27 | port ENV.fetch("PORT", 3000) 28 | 29 | # Allow puma to be restarted by `bin/rails restart` command. 30 | plugin :tmp_restart 31 | 32 | # Only use a pidfile when requested 33 | pidfile ENV["PIDFILE"] if ENV["PIDFILE"] 34 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Rails.application.routes.draw do 4 | get "welcome/index" 5 | 6 | # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. 7 | # Can be used by load balancers and uptime monitors to verify that the app is live. 8 | get "up" => "rails/health#show", as: :rails_health_check 9 | 10 | resources :articles do 11 | resources :comments 12 | end 13 | 14 | root "welcome#index" 15 | end 16 | -------------------------------------------------------------------------------- /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 bin/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: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket-<%= Rails.env %> 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket-<%= Rails.env %> 23 | 24 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name-<%= Rails.env %> 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /db/migrate/20210926221100_create_articles.rb: -------------------------------------------------------------------------------- 1 | class CreateArticles < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :articles do |t| 4 | t.string :title 5 | t.text :content 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20211216184102_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/20211216184103_create_action_text_tables.action_text.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from action_text (originally 20180528164100) 2 | class CreateActionTextTables < ActiveRecord::Migration[6.0] 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 :action_text_rich_texts, id: primary_key_type do |t| 8 | t.string :name, null: false 9 | t.text :body, size: :long 10 | t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type 11 | 12 | t.timestamps 13 | 14 | t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true 15 | end 16 | end 17 | 18 | private 19 | def primary_and_foreign_key_types 20 | config = Rails.configuration.generators 21 | setting = config.options[config.orm][:primary_key_type] 22 | primary_key_type = setting || :primary_key 23 | foreign_key_type = setting || :bigint 24 | [ primary_key_type, foreign_key_type ] 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20211216185503_create_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateComments < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :comments do |t| 4 | t.references :article, null: false, foreign_key: true 5 | t.text :content 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20230326154217_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 | return unless table_exists?(:active_storage_blobs) 5 | 6 | unless column_exists?(:active_storage_blobs, :service_name) 7 | add_column :active_storage_blobs, :service_name, :string 8 | 9 | if configured_service = ActiveStorage::Blob.service.name 10 | ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) 11 | end 12 | 13 | change_column :active_storage_blobs, :service_name, :string, null: false 14 | end 15 | end 16 | 17 | def down 18 | return unless table_exists?(:active_storage_blobs) 19 | 20 | remove_column :active_storage_blobs, :service_name 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20230326154218_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 | return unless table_exists?(:active_storage_blobs) 5 | 6 | # Use Active Record's configured type for primary key 7 | create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t| 8 | t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type 9 | t.string :variation_digest, null: false 10 | 11 | t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true 12 | t.foreign_key :active_storage_blobs, column: :blob_id 13 | end 14 | end 15 | 16 | private 17 | def primary_key_type 18 | config = Rails.configuration.generators 19 | config.options[config.orm][:primary_key_type] || :primary_key 20 | end 21 | 22 | def blobs_primary_key_type 23 | pkey_name = connection.primary_key(:active_storage_blobs) 24 | pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name } 25 | pkey_column.bigint? ? :bigint : pkey_column.type 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /db/migrate/20230326154219_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 | return unless table_exists?(:active_storage_blobs) 5 | 6 | change_column_null(:active_storage_blobs, :checksum, true) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /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.1].define(version: 2023_03_26_154219) do 14 | # These are extensions that must be enabled in order to support this database 15 | enable_extension "plpgsql" 16 | 17 | create_table "action_text_rich_texts", force: :cascade do |t| 18 | t.string "name", null: false 19 | t.text "body" 20 | t.string "record_type", null: false 21 | t.bigint "record_id", null: false 22 | t.datetime "created_at", null: false 23 | t.datetime "updated_at", null: false 24 | t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true 25 | end 26 | 27 | create_table "active_storage_attachments", force: :cascade do |t| 28 | t.string "name", null: false 29 | t.string "record_type", null: false 30 | t.bigint "record_id", null: false 31 | t.bigint "blob_id", null: false 32 | t.datetime "created_at", null: false 33 | t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" 34 | t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true 35 | end 36 | 37 | create_table "active_storage_blobs", force: :cascade do |t| 38 | t.string "key", null: false 39 | t.string "filename", null: false 40 | t.string "content_type" 41 | t.text "metadata" 42 | t.string "service_name", null: false 43 | t.bigint "byte_size", null: false 44 | t.string "checksum" 45 | t.datetime "created_at", null: false 46 | t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true 47 | end 48 | 49 | create_table "active_storage_variant_records", force: :cascade do |t| 50 | t.bigint "blob_id", null: false 51 | t.string "variation_digest", null: false 52 | t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true 53 | end 54 | 55 | create_table "articles", force: :cascade do |t| 56 | t.string "title" 57 | t.text "content" 58 | t.datetime "created_at", null: false 59 | t.datetime "updated_at", null: false 60 | end 61 | 62 | create_table "comments", force: :cascade do |t| 63 | t.bigint "article_id", null: false 64 | t.text "content" 65 | t.datetime "created_at", null: false 66 | t.datetime "updated_at", null: false 67 | t.index ["article_id"], name: "index_comments_on_article_id" 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 | add_foreign_key "comments", "articles" 73 | end 74 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file should ensure the existence of records required to run the application in every environment (production, 4 | # development, test). The code here should be idempotent so that it can be executed at any point in every environment. 5 | # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). 6 | # 7 | # Example: 8 | # 9 | # ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| 10 | # MovieGenre.find_or_create_by!(name: genre_name) 11 | # end 12 | -------------------------------------------------------------------------------- /development.Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1 2 | 3 | # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile 4 | ARG RUBY_VERSION=3.4.2 5 | FROM docker.io/library/ruby:$RUBY_VERSION-slim as base 6 | 7 | # OS Level Dependencies 8 | RUN --mount=type=cache,target=/var/cache/apt \ 9 | --mount=type=cache,target=/var/lib/apt,sharing=locked \ 10 | --mount=type=tmpfs,target=/var/log \ 11 | rm -f /etc/apt/apt.conf.d/docker-clean; \ 12 | echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; \ 13 | apt-get update -qq \ 14 | && apt-get install -yq --no-install-recommends \ 15 | build-essential \ 16 | gnupg2 \ 17 | less \ 18 | git \ 19 | libpq-dev \ 20 | postgresql-client \ 21 | libvips \ 22 | curl \ 23 | libjemalloc2 \ 24 | pkg-config \ 25 | libyaml-dev 26 | 27 | ENV LANG=C.UTF-8 \ 28 | BUNDLE_JOBS=4 \ 29 | BUNDLE_RETRY=3 30 | 31 | RUN gem update --system && gem install bundler 32 | 33 | WORKDIR /usr/src/app 34 | 35 | ENTRYPOINT ["./bin/docker-entrypoint-development"] 36 | 37 | EXPOSE 3000 38 | 39 | CMD ["./bin/rails", "server"] 40 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | web: Dockerfile 4 | run: 5 | web: bundle exec puma -C config/puma.rb 6 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/lib/tasks/.keep -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/log/.keep -------------------------------------------------------------------------------- /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/406-unsupported-browser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Your browser is not supported (406) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

Your browser is not supported.

62 |

Please upgrade your browser to continue.

63 |
64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /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/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/public/favicon.ico -------------------------------------------------------------------------------- /public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/public/icon.png -------------------------------------------------------------------------------- /public/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | databases: 2 | - name: mysite 3 | databaseName: mysite 4 | user: mysite 5 | plan: free 6 | 7 | services: 8 | - type: web 9 | name: mysite 10 | runtime: docker 11 | dockerfilePath: ./Dockerfile 12 | repo: https://github.com/ryanwi/rails7-on-docker 13 | region: oregon 14 | branch: main 15 | plan: free 16 | numInstances: 1 17 | healthCheckPath: /up 18 | preDeployCommand: bin/rails db:migrate 19 | envVars: 20 | - key: PORT 21 | value: 3000 22 | - key: DATABASE_URL 23 | fromDatabase: 24 | name: mysite 25 | property: connectionString 26 | - key: SECRET_KEY_BASE 27 | sync: false # placeholder for a value to be added in the dashboard 28 | - key: REDIS_HOST 29 | fromService: 30 | type: redis 31 | name: lightning 32 | property: host # available properties are listed below 33 | - key: REDIS_PORT 34 | fromService: 35 | type: redis 36 | name: lightning 37 | property: port 38 | - type: redis 39 | name: lightning 40 | ipAllowList: # required 41 | - source: 0.0.0.0/0 42 | description: everywhere 43 | plan: free 44 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /spec/helpers/articles_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | # Specs in this file have access to a helper object that includes 4 | # the ArticlesHelper. For example: 5 | # 6 | # describe ArticlesHelper do 7 | # describe "string concat" do 8 | # it "concats two strings with spaces" do 9 | # expect(helper.concat_strings("this","that")).to eq("this that") 10 | # end 11 | # end 12 | # end 13 | RSpec.describe ArticlesHelper, type: :helper do 14 | pending "add some examples to (or delete) #{__FILE__}" 15 | end 16 | -------------------------------------------------------------------------------- /spec/helpers/comments_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | # Specs in this file have access to a helper object that includes 4 | # the CommentsHelper. For example: 5 | # 6 | # describe CommentsHelper do 7 | # describe "string concat" do 8 | # it "concats two strings with spaces" do 9 | # expect(helper.concat_strings("this","that")).to eq("this that") 10 | # end 11 | # end 12 | # end 13 | RSpec.describe CommentsHelper, type: :helper do 14 | pending "add some examples to (or delete) #{__FILE__}" 15 | end 16 | -------------------------------------------------------------------------------- /spec/helpers/welcome_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | # Specs in this file have access to a helper object that includes 4 | # the WelcomeHelper. For example: 5 | # 6 | # describe WelcomeHelper do 7 | # describe "string concat" do 8 | # it "concats two strings with spaces" do 9 | # expect(helper.concat_strings("this","that")).to eq("this that") 10 | # end 11 | # end 12 | # end 13 | RSpec.describe WelcomeHelper, type: :helper do 14 | pending "add some examples to (or delete) #{__FILE__}" 15 | end 16 | -------------------------------------------------------------------------------- /spec/models/article_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe Article, type: :model do 4 | pending "add some examples to (or delete) #{__FILE__}" 5 | end 6 | -------------------------------------------------------------------------------- /spec/models/comment_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe Comment, type: :model do 4 | pending "add some examples to (or delete) #{__FILE__}" 5 | end 6 | -------------------------------------------------------------------------------- /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 | require 'spec_helper' 5 | ENV['RAILS_ENV'] ||= 'test' 6 | require File.expand_path('../config/environment', __dir__) 7 | # Prevent database truncation if the environment is production 8 | abort('The Rails environment is running in production mode!') if Rails.env.production? 9 | require 'rspec/rails' 10 | # Add additional requires below this line. Rails is not loaded until this point! 11 | 12 | # Requires supporting ruby files with custom matchers and macros, etc, in 13 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are 14 | # run as spec files by default. This means that files in spec/support that end 15 | # in _spec.rb will both be required and run as specs, causing the specs to be 16 | # run twice. It is recommended that you do not name files matching this glob to 17 | # end with _spec.rb. You can configure this pattern with the --pattern 18 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. 19 | # 20 | # The following line is provided for convenience purposes. It has the downside 21 | # of increasing the boot-up time by auto-requiring all files in the support 22 | # directory. Alternatively, in the individual `*_spec.rb` files, manually 23 | # require only the support files necessary. 24 | # 25 | # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } 26 | 27 | # Checks for pending migrations and applies them before tests are run. 28 | # If you are not using ActiveRecord, you can remove these lines. 29 | begin 30 | ActiveRecord::Migration.maintain_test_schema! 31 | rescue ActiveRecord::PendingMigrationError => e 32 | puts e.to_s.strip 33 | exit 1 34 | end 35 | RSpec.configure do |config| 36 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 37 | config.fixture_paths = [ 38 | Rails.root.join('spec/fixtures') 39 | ] 40 | 41 | # If you're not using ActiveRecord, or you'd prefer not to run each of your 42 | # examples within a transaction, remove the following line or assign false 43 | # instead of true. 44 | config.use_transactional_fixtures = true 45 | 46 | # You can uncomment this line to turn off ActiveRecord support entirely. 47 | # config.use_active_record = false 48 | 49 | # RSpec Rails can automatically mix in different behaviours to your tests 50 | # based on their file location, for example enabling you to call `get` and 51 | # `post` in specs under `spec/controllers`. 52 | # 53 | # You can disable this behaviour by removing the line below, and instead 54 | # explicitly tag your specs with their type, e.g.: 55 | # 56 | # RSpec.describe UsersController, type: :controller do 57 | # # ... 58 | # end 59 | # 60 | # The different available types are documented in the features, such as in 61 | # https://relishapp.com/rspec/rspec-rails/docs 62 | config.infer_spec_type_from_file_location! 63 | 64 | # Filter lines from Rails gems in backtraces. 65 | config.filter_rails_from_backtrace! 66 | # arbitrary gems may also be filtered via: 67 | # config.filter_gems_from_backtrace("gem name") 68 | end 69 | -------------------------------------------------------------------------------- /spec/requests/articles_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | # This spec was generated by rspec-rails when you ran the scaffold generator. 4 | # It demonstrates how one might use RSpec to test the controller code that 5 | # was generated by Rails when you ran the scaffold generator. 6 | # 7 | # It assumes that the implementation code is generated by the rails scaffold 8 | # generator. If you are using any extension libraries to generate different 9 | # controller code, this generated spec may or may not pass. 10 | # 11 | # It only uses APIs available in rails and/or rspec-rails. There are a number 12 | # of tools you can use to make these specs even more expressive, but we're 13 | # sticking to rails and rspec-rails APIs to keep things simple and stable. 14 | 15 | RSpec.describe "/articles", type: :request do 16 | # Article. As you add validations to Article, be sure to 17 | # adjust the attributes here as well. 18 | let(:valid_attributes) { 19 | skip("Add a hash of attributes valid for your model") 20 | } 21 | 22 | let(:invalid_attributes) { 23 | skip("Add a hash of attributes invalid for your model") 24 | } 25 | 26 | describe "GET /index" do 27 | it "renders a successful response" do 28 | Article.create! valid_attributes 29 | get articles_url 30 | expect(response).to be_successful 31 | end 32 | end 33 | 34 | describe "GET /show" do 35 | it "renders a successful response" do 36 | article = Article.create! valid_attributes 37 | get article_url(article) 38 | expect(response).to be_successful 39 | end 40 | end 41 | 42 | describe "GET /new" do 43 | it "renders a successful response" do 44 | get new_article_url 45 | expect(response).to be_successful 46 | end 47 | end 48 | 49 | describe "GET /edit" do 50 | it "render a successful response" do 51 | article = Article.create! valid_attributes 52 | get edit_article_url(article) 53 | expect(response).to be_successful 54 | end 55 | end 56 | 57 | describe "POST /create" do 58 | context "with valid parameters" do 59 | it "creates a new Article" do 60 | expect { 61 | post articles_url, params: { article: valid_attributes } 62 | }.to change(Article, :count).by(1) 63 | end 64 | 65 | it "redirects to the created article" do 66 | post articles_url, params: { article: valid_attributes } 67 | expect(response).to redirect_to(article_url(Article.last)) 68 | end 69 | end 70 | 71 | context "with invalid parameters" do 72 | it "does not create a new Article" do 73 | expect { 74 | post articles_url, params: { article: invalid_attributes } 75 | }.to change(Article, :count).by(0) 76 | end 77 | 78 | it "renders a successful response (i.e. to display the 'new' template)" do 79 | post articles_url, params: { article: invalid_attributes } 80 | expect(response).to be_successful 81 | end 82 | end 83 | end 84 | 85 | describe "PATCH /update" do 86 | context "with valid parameters" do 87 | let(:new_attributes) { 88 | skip("Add a hash of attributes valid for your model") 89 | } 90 | 91 | it "updates the requested article" do 92 | article = Article.create! valid_attributes 93 | patch article_url(article), params: { article: new_attributes } 94 | article.reload 95 | skip("Add assertions for updated state") 96 | end 97 | 98 | it "redirects to the article" do 99 | article = Article.create! valid_attributes 100 | patch article_url(article), params: { article: new_attributes } 101 | article.reload 102 | expect(response).to redirect_to(article_url(article)) 103 | end 104 | end 105 | 106 | context "with invalid parameters" do 107 | it "renders a successful response (i.e. to display the 'edit' template)" do 108 | article = Article.create! valid_attributes 109 | patch article_url(article), params: { article: invalid_attributes } 110 | expect(response).to be_successful 111 | end 112 | end 113 | end 114 | 115 | describe "DELETE /destroy" do 116 | it "destroys the requested article" do 117 | article = Article.create! valid_attributes 118 | expect { 119 | delete article_url(article) 120 | }.to change(Article, :count).by(-1) 121 | end 122 | 123 | it "redirects to the articles list" do 124 | article = Article.create! valid_attributes 125 | delete article_url(article) 126 | expect(response).to redirect_to(articles_url) 127 | end 128 | end 129 | end 130 | -------------------------------------------------------------------------------- /spec/requests/comments_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "Comments", type: :request do 4 | describe "GET /index" do 5 | pending "add some examples (or delete) #{__FILE__}" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/requests/welcome_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "Welcomes", type: :request do 4 | describe "GET /index" do 5 | pending "add some examples (or delete) #{__FILE__}" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/routing/articles_routing_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | RSpec.describe ArticlesController, type: :routing do 4 | describe "routing" do 5 | it "routes to #index" do 6 | expect(get: "/articles").to route_to("articles#index") 7 | end 8 | 9 | it "routes to #new" do 10 | expect(get: "/articles/new").to route_to("articles#new") 11 | end 12 | 13 | it "routes to #show" do 14 | expect(get: "/articles/1").to route_to("articles#show", id: "1") 15 | end 16 | 17 | it "routes to #edit" do 18 | expect(get: "/articles/1/edit").to route_to("articles#edit", id: "1") 19 | end 20 | 21 | 22 | it "routes to #create" do 23 | expect(post: "/articles").to route_to("articles#create") 24 | end 25 | 26 | it "routes to #update via PUT" do 27 | expect(put: "/articles/1").to route_to("articles#update", id: "1") 28 | end 29 | 30 | it "routes to #update via PATCH" do 31 | expect(patch: "/articles/1").to route_to("articles#update", id: "1") 32 | end 33 | 34 | it "routes to #destroy" do 35 | expect(delete: "/articles/1").to route_to("articles#destroy", id: "1") 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file was generated by the `rails generate rspec:install` command. Conventionally, all 4 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 5 | # The generated `.rspec` file contains `--require spec_helper` which will cause 6 | # this file to always be loaded, without a need to explicitly require it in any 7 | # files. 8 | # 9 | # Given that it is always loaded, you are encouraged to keep this file as 10 | # light-weight as possible. Requiring heavyweight dependencies from this file 11 | # will add to the boot time of your test suite on EVERY test run, even for an 12 | # individual file that may not need all of that loaded. Instead, consider making 13 | # a separate helper file that requires the additional dependencies and performs 14 | # the additional setup, and require it from the spec files that actually need 15 | # it. 16 | # 17 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 18 | RSpec.configure do |config| 19 | # rspec-expectations config goes here. You can use an alternate 20 | # assertion/expectation library such as wrong or the stdlib/minitest 21 | # assertions if you prefer. 22 | config.expect_with :rspec do |expectations| 23 | # This option will default to `true` in RSpec 4. It makes the `description` 24 | # and `failure_message` of custom matchers include text for helper methods 25 | # defined using `chain`, e.g.: 26 | # be_bigger_than(2).and_smaller_than(4).description 27 | # # => "be bigger than 2 and smaller than 4" 28 | # ...rather than: 29 | # # => "be bigger than 2" 30 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 31 | end 32 | 33 | # rspec-mocks config goes here. You can use an alternate test double 34 | # library (such as bogus or mocha) by changing the `mock_with` option here. 35 | config.mock_with :rspec do |mocks| 36 | # Prevents you from mocking or stubbing a method that does not exist on 37 | # a real object. This is generally recommended, and will default to 38 | # `true` in RSpec 4. 39 | mocks.verify_partial_doubles = true 40 | end 41 | 42 | # This option will default to `:apply_to_host_groups` in RSpec 4 (and will 43 | # have no way to turn it off -- the option exists only for backwards 44 | # compatibility in RSpec 3). It causes shared context metadata to be 45 | # inherited by the metadata hash of host groups and examples, rather than 46 | # triggering implicit auto-inclusion in groups with matching metadata. 47 | config.shared_context_metadata_behavior = :apply_to_host_groups 48 | 49 | # The settings below are suggested to provide a good initial experience 50 | # with RSpec, but feel free to customize to your heart's content. 51 | # # This allows you to limit a spec run to individual examples or groups 52 | # # you care about by tagging them with `:focus` metadata. When nothing 53 | # # is tagged with `:focus`, all examples get run. RSpec also provides 54 | # # aliases for `it`, `describe`, and `context` that include `:focus` 55 | # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. 56 | # config.filter_run_when_matching :focus 57 | # 58 | # # Allows RSpec to persist some state between runs in order to support 59 | # # the `--only-failures` and `--next-failure` CLI options. We recommend 60 | # # you configure your source control system to ignore this file. 61 | # config.example_status_persistence_file_path = "spec/examples.txt" 62 | # 63 | # # Limits the available syntax to the non-monkey patched syntax that is 64 | # # recommended. For more details, see: 65 | # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ 66 | # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ 67 | # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode 68 | # config.disable_monkey_patching! 69 | # 70 | # # Many RSpec users commonly either run the entire suite or an individual 71 | # # file, and it's useful to allow more verbose output when running an 72 | # # individual spec file. 73 | # if config.files_to_run.one? 74 | # # Use the documentation formatter for detailed output, 75 | # # unless a formatter has already been configured 76 | # # (e.g. via a command-line flag). 77 | # config.default_formatter = "doc" 78 | # end 79 | # 80 | # # Print the 10 slowest examples and example groups at the 81 | # # end of the spec run, to help surface which specs are running 82 | # # particularly slow. 83 | # config.profile_examples = 10 84 | # 85 | # # Run specs in random order to surface order dependencies. If you find an 86 | # # order dependency and want to debug it, you can fix the order by providing 87 | # # the seed, which is printed after each run. 88 | # # --seed 1234 89 | # config.order = :random 90 | # 91 | # # Seed global randomization in this process using the `--seed` CLI option. 92 | # # Setting this allows you to use `--seed` to deterministically reproduce 93 | # # test failures related to randomization by passing the same `--seed` value 94 | # # as the one that triggered the failure. 95 | # Kernel.srand config.seed 96 | end 97 | -------------------------------------------------------------------------------- /spec/views/articles/edit.html.erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "articles/edit", type: :view do 4 | before(:each) do 5 | @article = assign(:article, Article.create!( 6 | title: "MyString", 7 | content: "MyContent" 8 | )) 9 | end 10 | 11 | it "renders the edit article form" do 12 | render 13 | 14 | assert_select "form[action=?][method=?]", article_path(@article), "post" do 15 | assert_select "input[name=?]", "article[title]" 16 | 17 | # TODO: with rich_text, this is not a textarea 18 | # assert_select "textarea[name=?]", "article[content]" 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/views/articles/index.html.erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "articles/index", type: :view do 4 | before(:each) do 5 | assign(:articles, [ 6 | Article.create!( 7 | title: "Title", 8 | content: "MyText" 9 | ), 10 | Article.create!( 11 | title: "Title", 12 | content: "MyText" 13 | ) 14 | ]) 15 | end 16 | 17 | xit "renders a list of articles" do 18 | render 19 | assert_select "tr>td", text: "Title".to_s, count: 2 20 | assert_select "tr>td", text: "MyText".to_s, count: 2 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/views/articles/new.html.erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "articles/new", type: :view do 4 | before(:each) do 5 | assign(:article, Article.new( 6 | title: "MyString", 7 | content: "MyContent" 8 | )) 9 | end 10 | 11 | it "renders new article form" do 12 | render 13 | 14 | assert_select "form[action=?][method=?]", articles_path, "post" do 15 | assert_select "input[name=?]", "article[title]" 16 | 17 | # TODO: with rich_text, this is not a textarea 18 | # assert_select "textarea[name=?]", "article[content]" 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/views/articles/show.html.erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "articles/show", type: :view do 4 | before(:each) do 5 | @article = assign(:article, Article.create!( 6 | title: "Title", 7 | content: "MyContent" 8 | )) 9 | end 10 | 11 | it "renders attributes in

" do 12 | render 13 | expect(rendered).to match(/Title/) 14 | expect(rendered).to match(/MyContent/) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /storage/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/storage/.keep -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/tmp/.keep -------------------------------------------------------------------------------- /tmp/pids/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/tmp/pids/.keep -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/vendor/.keep -------------------------------------------------------------------------------- /vendor/javascript/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanwi/rails7-on-docker/a5133359693a12289254ee60e76c03b955a8819e/vendor/javascript/.keep --------------------------------------------------------------------------------