Ruby On Rails - HVboom/HowTo-DigitalOcean GitHub Wiki

Create a new application using the latest released Ruby & Rails version

Precondition

  • A Development User is created including the RVM setup
  • Create a new directory for your application and inside follow the next steps.

Define an initial Gemfile

#ruby=ruby-3.3.5
#ruby-gemset=HVPlayground
#
source 'https://rubygems.org'
git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

ruby '3.3.5'

gem 'rails', '7.2.1'

Create the new application

# --force : update the Gemfile
# --skip-bundle : the Gemfile has to be fixed first
#    the changed Gemfile does not contain the Gemset definition anymore
#    the path to the Rails gem is wrong
bundle exec rails new . --force --skip-bundle --skip-test --database=postgresql --css=tailwind

Adjust the updated Gemfile to contain the Gemset definition again

#ruby=ruby-3.3.5
#ruby-gemset=HVPlayground
#
source 'https://rubygems.org'
git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

ruby '3.3.5'

...

Install all Gems

Run commands:

bundle install
bundle update
bundle clean --force

Setup the DB connection

Store the connection attributes in the Credential file

Edit the file: rails credentials:edit

Example:

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: <run command 'rails secret'>


db_connection: &db_connection
  db_username: hvplayground
  db_password: <secret password>

development:
  db_name: hvplayground_dev
  <<: *db_connection

test:
  db_name: hvplayground_test
  <<: *db_connection

demo:
  db_name: hvplayground_demo
  <<: *db_connection

production:
  db_name: hvplayground_prod
  <<: *db_connection

Adjust the database configuration config/database.yml

The connection parameter are safely stored in the Credentials file

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: <%= Rails.application.credentials[Rails.env.to_sym][:db_name] %>
  username: <%= Rails.application.credentials[Rails.env.to_sym][:db_username] %>
  password: <%= Rails.application.credentials[Rails.env.to_sym][:db_password] %>

development:
  <<: *default

test:
  <<: *default

demo:
  <<: *default

production:
  <<: *default

Create a DB user for the application

psql -U postgres

CREATE ROLE hvplayground WITH LOGIN CREATEDB PASSWORD '<secure password>';

\q

Create the development DB

rails db:setup
rails db:migrate

Allow connections to the application running by Phusion Passenger

  • Add following line to the end of config/application.rb

    ...
    
        # Allow everything from my hosts
        config.hosts << /\Ahv.*\.hvboom\.org\Z/
      end
    end
  • Setup Apache configuration

    <Macro RailsProduction $user $application>
      <VirtualHost *:443>
        # Serve rails applications in production like mode
    
        UseCanonicalName Off
    
        ServerName $application.HVboom.biz
        VirtualDocumentRoot "/home/$user/RubyOnRails/$application/public"
    
        PassengerAppEnv "production"
    
        RailsBaseURI "/"
        <Directory "/home/$user/RubyOnRails/$application/public">
          Require all granted
          Options -MultiViews
        </Directory>
    
        SSLEngine on
      </VirtualHost>
    </Macro>
    
    <Macro Rails $environment $user $application>
      <VirtualHost *:443>
        # Serve rails applications in production like mode
    
        UseCanonicalName Off
    
        ServerName $application.$user.HVboom.biz
        VirtualDocumentRoot "/home/$user/RubyOnRails/$application/public"
    
        PassengerAppEnv "$environment"
    
        RailsBaseURI "/"
        <Directory "/home/$user/RubyOnRails/$application/public">
          Require all granted
          Options -MultiViews
        </Directory>
      
        SSLEngine on
      </VirtualHost> 
    </Macro>
    
    Use Rails development mario            HVDigitalSafe
    Use Rails demo        demo             HVDigitalSafe
    Use RailsProduction   hvdigitalsafe    HVDigitalSafe
    
    Use Rails development mario            HVKeyGuard
    Use Rails demo        demo             HVKeyGuard
    Use RailsProduction   hvkeyguard       HVKeyGuard
    
    Use Rails development mario            HVPlayground
    Use Rails demo        demo             HVPlayground
    Use RailsProduction   hvplayground     HVPlayground
    
    Use Rails development mario            HVMembership
    Use Rails demo        demo             HVMembership
    Use RailsProduction   hvmembership     HVMembership
    
    Use Rails development mario            HVControlTower
    Use Rails demo        demo             HVControlTower
    Use RailsProduction   hvcontroltower   HVControlTower
    
    Use Rails development mario            HVEntitlement
    Use Rails demo        demo             HVEntitlement
    Use RailsProduction   hventitlement    HVEntitlement
    
    Use Rails development mario            HVLogger
    Use Rails demo        demo             HVLogger
    Use Rails production  hvlogger         HVLogger
    
    Use Rails development mario            HVLookBook
    Use Rails demo        demo             HVLookBook
    Use Rails production  hvlookbook       HVLookBook
    
    Use Rails development mario            HVTurtleGraphics
    Use Rails demo        demo             HVTurtleGraphics
    Use Rails production  hvturtlegraphics HVTurtleGraphics
    
    UndefMacro RailsProduction
    UndefMacro Rails
    • Enable necessary modules

      sudo a2enmod macro
      sudo a2enmod vhost_alias
      
      sudo a2ensite 030_vhost_443_rails.conf  # enable Rails applications
      sudo systemctl reload apache2.service

Visit your application

https://hvplayground.mario.hvboom.org 🥳

Caution

Everything below is outdated!

Create a new application using edge Rails

  • Use script create_edge_rails_project stored at /usr/local/share/bin:

    #!/usr/bin/env bash
    
    # TODO: check parameter & display usage section
    project=$1
    ruby_version='ruby-'${2:-2.3.1}
    
    project_path=$HOME/RubyOnRails/$project
    gemfile=$project_path/Gemfile
    
    # TODO: check RVM environment - rvm list known - ...
    # source necessary RVM scripts into current shell environment
    source $HOME/.rvm/scripts/rvm
    type rvm | head -n 1 | grep -q "rvm is a function"
    success=$?
    if ! [[ $success ]]
    then
      echo "RVM is not installed - $success"
      exit $success
    fi
    
    # Save an existing project
    # TODO: create save directory path using a timestamp
    if [[ -e $project_path ]]
    then
      saved_project_path=$project_path'.SAVED'
      echo "Project already exists - saved as $saved_project_path."
      mv $project_path $saved_project_path
    fi
    
    # Create Gemfile for edge rails
    mkdir $project_path
    cat <<EOF >$gemfile
    #ruby=$ruby_version
    #ruby-gemset=$project
    #
    source 'https://rubygems.org'
    
    gem 'rails', github: 'rails/rails'
    EOF
    
    # Install rails from GitHub repository - RVM environment automatically starts the bundler
    cd $project_path
    
    # Create rails project
    # --dev   : using the edge version
    # --force : update the Gemfile
    # --skip-bundle : the Gemfile has to be fixed first
    #    the changed Gemfile does not contain the Gemset definition anymore
    #    the path to the Rails gem is wrong
    bundle exec rails new . --dev --force --skip-bundle --database=mysql
    
    # Fix Gemfile
    tmp_gemfile=/tmp/Gemfile_$project
    
    cat <<EOF >$tmp_gemfile
    #ruby=$ruby_version
    #ruby-gemset=$project
    #
    source 'https://rubygems.org'
    
    EOF
    
    tail -n+3 Gemfile | head -n1 | sed 's/gems\"$/bundler\/gems\"/' >> $tmp_gemfile
    tail -n+4 Gemfile >> $tmp_gemfile
    mv $tmp_gemfile $gemfile
    
    # Install all gems
    bundle install
    
    # Ensure to restart the application
    touch $project_path/tmp/restart.txt
  • Rails App Composer - manual setup

    • Preferences

      # Setup
      prefs[:dev_webserver] = 'passenger'
      prefs[:prod_webserver] = 'passenger'
      prefs[:database] = 'mysql'
      prefs[:templates] = 'haml'
      prefs[:tests] = 'rspec'
      prefs[:continuous_testing] = 'guard'
      prefs[:frontend] = 'bootstrap3'
      prefs[:email] = 'smtp'
      prefs[:authentication] = 'device'
      prefs[:devise_modules] = 'inevitable'
      prefs[:authorization] = 'pundit'
      prefs[:dashboard] = 'none'
      prefs[:form_builder] = 'simple_form'
      
      # Gems
      
      # Init
      
      # Extras
      prefs[:rvmrc] = false
      prefs[:quiet_assets] = true
      prefs[:local_env_file] = 'none'
      prefs[:better_errors] = true
      prefs[:pry] = true
      prefs[:rubocop] = false
      prefs[:disable_turbolinks] = false
      prefs[:ban_spiders] = true
      prefs[:github] = false
      
      # Admin
      prefs[:admin] = 'rails_admin'
      
      # Analytics
      prefs[:analytics] = 'none'
      
      # Core - not used
      
      # Deployment - not used
      prefs[:deployment] = 'capistrano3'
      
      # Device
      
      # Email
      
      # Email Dev - not used
      prefs[:mailcatcher] = false
      prefs[:mail_view] = false
      
      # Frontend
      
      # Git
      prefs[:git] = true
      
      # Learn rails - not used
      
      # Locale
      prefs[:locale] = 'en'
      
      # Omniauth - not use
      
      # Pages - not use
      
      # Rails * - not use
      
      # Railsapps - not use
      
      # Readme - not use
      
      # Roles
      
      # Tests
    • Gemfile

      # Gems
      gem 'mysql2'
      
      gem 'haml-rails'
      gem 'html2haml', :group => :development
      
      gem 'rails_apps_testing', :group => :development
      gem 'rspec-rails', :group => [:development, :test]
      gem 'spring-commands-rspec', :group => :development
      gem 'factory_girl_rails', :group => [:development, :test]
      gem 'faker', :group => [:development, :test]
      gem 'capybara', :group => :test
      gem 'database_cleaner', :group => :test
      gem 'launchy', :group => :test
      gem 'selenium-webdriver', :group => :test
      
      gem 'guard-bundler', :group => :development
      gem 'guard-rails', :group => :development
      gem 'guard-rspec', :group => :development
      gem 'rb-inotify', :group => :development, :require => false
      gem 'rb-fsevent', :group => :development, :require => false
      gem 'rb-fchange', :group => :development, :require => false
      
      gem 'rails_layout', :group => :development
      gem 'bootstrap-sass'
      
      gem 'devise'
      gem 'devise_invitable'
      
      gem 'pundit'
      
      gem 'simple_form'
      
      # Extras
      gem 'quiet_assets', :group => :development
      gem 'better_errors', :group => :development
      gem 'binding_of_caller', :group => :development
      gem 'pry-rails', :group => [:development, :test]
      gem 'pry-rescue', :group => [:development, :test]
      
      # Admin
      gem 'rails_admin'
      
      # Locale
      gem 'devise-i18n'
    • Scripts

      • Stage 2
        # Gems
        copy_from_repo 'config/database-mysql.yml'
        gsub_file "config/database.yml", /username: .*/, "username: #{app_name}"
        gsub_file "config/database.yml", /password:/, "password: #{mysql_password}"
        gsub_file "config/database.yml", /database: myapp_development/, "database: #{app_name}_development"
        gsub_file "config/database.yml", /database: myapp_test/,        "database: #{app_name}_test"
        gsub_file "config/database.yml", /database: myapp_production/,  "database: #{app_name}_production"
        run 'bundle exec rake db:create:all'
        
        generate 'simple_form:install --bootstrap'
        
        # Extras
        gsub_file 'public/robots.txt', /# User-Agent/, 'User-Agent'
        gsub_file 'public/robots.txt', /# Disallow/, 'Disallow'
        
        # Admin
        generate 'rails_admin:install'
        
        # Device
        gsub_file 'config/initializers/filter_parameter_logging.rb', /:password/, ':password, :password_confirmation'
        generate 'devise:install'
        generate 'devise_invitable:install'
        generate 'devise user'
        
        gsub_file 'app/models/user.rb', /:registerable,/, ":registerable, :confirmable,"
        generate 'migration AddConfirmableToUsers confirmation_token:string confirmed_at:datetime confirmation_sent_at:datetime unconfirmed_email:string'
        run 'bundle exec rake db:migrate'
        
        # Email
        email_text = <<-TEXT
          # ActionMailer Config
          config.action_mailer.default_url_options = { :host => Rails.application.secrets.domain_name }
          config.action_mailer.delivery_method = :smtp
          config.action_mailer.perform_deliveries = true
          config.action_mailer.raise_delivery_errors = false

TEXT

  inject_into_file 'config/environments/development.rb', email_text, :after => "config.assets.debug = true"
  inject_into_file 'config/environments/production.rb', email_text, :after => "config.active_support.deprecation = :notify"

  # Frontend
  generate 'layout:install bootstrap3 -f'

  # Roles
  generate 'migration AddRoleToUsers role:integer'
  role_boilerplate = "  enum role: [:user, :vip, :admin]\n  after_initialize :set_default_role, :if => :new_record?\n\n"
  role_boilerplate << "  def set_default_role\n    self.role ||= :user\n  end\n\n"
  inject_into_class 'app/models/user.rb', 'User', role_boilerplate

  # Tests
  generate 'testing:configure rspec -f'
  run 'bundle exec guard init'
  ```

* Stage 3
  ```Bash
  # Extras
  inject_into_file 'config/secrets.yml', "\n" + "  trusted_ip: 46.101.219.241", :after => "development:"
  inject_into_file 'config/environments/development.rb', 'BetterErrors::Middleware.allow_ip! Rails.application.secrets.trusted_ip', :after => "config.assets.debug = true"

  # ???
  inject_into_file 'config/secrets.yml', "\n" + "  domain_name: example.com", :after => "development:"
  inject_into_file 'config/secrets.yml', "\n" + "  domain_name: <%= ENV[\"DOMAIN_NAME\"] %>", :after => "production:"

  inject_into_file 'config/secrets.yml', "\n" + '  domain_name: example.com' + " ", :after => "test:"
  inject_into_file 'config/secrets.yml', "\n" + "  admin_name: First User\n  admin_email: [email protected]\n  admin_password: changeme", :after => "development:"
  inject_into_file 'config/secrets.yml', "\n" + "  admin_name: <%= ENV[\"ADMIN_NAME\"] %>\n  admin_email: <%= ENV[\"ADMIN_EMAIL\"] %>\n  admin_password: <%= ENV[\"ADMIN_PASSWORD\"] %>", :after => "production:"
  append_file 'config/application.yml', "ADMIN_NAME:First User\nADMIN_EMAIL:[email protected]\nADMIN_PASSWORD:changeme\n"
  gsub_file 'config/initializers/devise.rb', /'[email protected]'/, "'no-reply@' + Rails.application.secrets.domain_name"

  copy_file destination_root + '/config/application.yml', destination_root + '/config/application.example.yml'

  copy_from_repo 'db/seeds.rb', :repo => 'https://raw.github.com/RailsApps/rails-devise/master/'
  copy_from_repo 'app/services/create_admin_service.rb', :repo => 'https://raw.github.com/RailsApps/rails-devise-pundit/master/'

  append_file 'db/seeds.rb' do <<-FILE

Environment variables (ENV['...']) can be set in the file config/application.yml.

FILE

  inject_into_file 'app/services/create_admin_service.rb', "        user.confirm!\n", :after => "user.password_confirmation = Rails.application.secrets.admin_password\n"
  run 'bundle exec rake db:migrate'
  generate 'devise_invitable user'

  run 'bundle exec rake db:seed'

  generate 'layout:devise bootstrap3 -f'

  generate 'layout:navigation -f'

  # Tests
  generate 'testing:configure devise -f'

  inject_into_file 'spec/factories/users.rb', "    confirmed_at Time.now\n", :after => "factory :user do\n"
  default_url = '  config.action_mailer.default_url_options = { :host => Rails.application.secrets.domain_name }'
  inject_into_file 'config/environments/test.rb', default_url, :after => "delivery_method = :test\n"
  gsub_file 'spec/features/users/user_edit_spec.rb', /successfully./, 'successfully,'
  gsub_file 'spec/features/visitors/sign_up_spec.rb', /Welcome! You have signed up successfully./, 'A message with a confirmation'

  generate 'testing:configure pundit -f'
  inject_into_file 'spec/factories/users.rb', "    confirmed_at Time.now\n", :after => "factory :user do\n"
  ```

* Stage 4
  ```Bash
  # Extras
  %w{
    public/index.html
    app/assets/images/rails.png
  }.each { |file| remove_file file }

  # Git
  copy_from 'https://raw.github.com/RailsApps/rails-composer/master/files/gitignore.txt', '.gitignore'
  git :init
  git :add => '-A'
  git :commit => '-qm "Initial commit"'
  ```

Setup a new application using the Rails App Composer

Ideas taken form this Tutorial

  • Create a new MySQL user for the application using phpMyAdmin:

  • Create a default file: $HOME/tmp/RailsAppTemplate.yml

recipes:
- admin
- deployment
- devise
- email
- email_dev
- extras
- frontend
- gems
- git
- init
- locale
- readme
- roles
- setup
- tests

prefs:
  :admin: rails_admin
  :deployment: capistrano3
  :authentication: devise
  :devise_modules: invitable
  :email: smtp
  :mailcatcher: yes
  :mail_view: yes
  :disable_turbolinks: false
  :ban_spiders: yes
  :git: yes
  :github: false
  :local_env_file: figaro
  :quiet_assets: yes
  :better_errors: yes
  :pry: yes
  :rubocop: yes
  :form_builder: simple_form
  :frontend: bootstrap3
  :dev_webserver: passenger
  :prod_webserver: same
  :database: mysql
  :drop_database: yes
  :skip_seeds: yes
  :rvmrc: false
  :templates: haml
  :tests: rspec
  :continuous_testing: guard
  :authorization: pundit
  :locale: de
  :dashboard: none
  :integration: cucumber
  :fixtures: factory_girl

gems:
- "'rails_admin_pundit', :github => 'sudosu/rails_admin_pundit'"

args:
  :skip_test_unit: yes
  :skip_active_record: false
  • Create a template file based on the default file: $HOME/tmp/RailsAppTemplate.rb
rails_apps_composer template $HOME/tmp/RailsAppTemplate.rb -d $HOME/tmp/RailsAppTemplate.yml
  • Use the template to create a new Rails application

ATTENTION: currently the default file does not produce the same result as manual setup using the same selections.

If prompted to define the MySQL user, please answer the question. Otherwise you will not be prompted to enter the password.

cd $HOME

# create application directory
mkdir -p RubyOnRails/RailsAppTemplate
cd RubyOnRails/RailsAppTemplate

# use a specific ruby version and a dedicated gems
rvm use ruby-2.2.3@RailsAppTemplate --ruby-version --create

# use rails composer to create a new application
gem install rails
gem install rails_apps_composer

# use the template file to create the application
# rails new . -m $HOME/tmp/RailsAppTemplate.rb

rails_apps_composer new .

Used features

⚠️ **GitHub.com Fallback** ⚠️