Table: RailsNotes
User: dreamable
Created at: 2021-01-12 04:40:23 UTC
Updated at: 2021-08-24 22:43:46 UTC
Reference:(Table ID 3, Record ID 11)

标题 :
Rails建站指南
笔记 :

How to start a new Rails app

System

Install ubuntu 18.04 LTS

DB:PostgreSQL

Guide: default version is 10, we use the latest

    sudo apt-get install wget ca-certificates
    wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
    sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
    sudo apt-get install postgresql postgresql-contrib libpq-dev
    sudo -u postgres createuser db_user -s
    sudo -u postgres psql
    postgres=# \password (db_user)

By default, psql use peer neection (login by linux user, no password).
To change it, modify /etc/postgresql/9.5/main/pg_hba.conf
from:
local all all peer
to:
local all all md5
then restart by
sudo service postgresql restart

Command to login:
psql -U db_user -d postgres # must specify db

Rails

Guide

  1. Rails

    sudo apt install curl
    curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
    
    sudo apt-get update
    sudo apt-get install git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev nodejs yarn
    
    cd
    git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(rbenv init -)"' >> ~/.bashrc
    exec $SHELL
    
    git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
    echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
    exec $SHELL
    
    rbenv install 2.6.5
    rbenv global 2.6.5
    ruby -v
    
    gem install bundler
    gem install rails -v 6.0.0
    rbenv rehash
    rails -v
    
  2. Rails app

    rails new my_site -d postgresql
    
    # configure db database.yml
    # add domain
    add config.hosts << "yourdomain.com" to config/environments/development.rb
    # config generator in application.rb
    config.generators do |g|
      # Disable jbuilder as we use JR
      # g.jbuilder        false
      ## Disable empty files
      # helper files
      g.helper          false
      # assets files
      g.assets          false
    end
    

Ngnix

Guide

    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
    sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list'
    sudo apt-get update
    sudo apt-get install -y nginx-extras libnginx-mod-http-passenger
    if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi
    sudo ls /etc/nginx/conf.d/mod-http-passenger.conf
    sudo vim /etc/nginx/conf.d/mod-http-passenger.conf
    # We simply want to change the passenger_ruby line to match the following:
    passenger_ruby /home/<deploy_user>/.rbenv/shims/ruby;
    sudo service nginx start

Deploy

Guide

  1. Add the following gems to our Gemfile

    gem 'capistrano', '~> 3.11'
    gem 'capistrano-rails', '~> 1.4'
    gem 'capistrano-passenger', '~> 0.2.0'
    gem 'capistrano-rbenv', '~> 2.1', '>= 2.1.4'
    
  2. Generate template

    bundle
    # use cap in rbenv, source ~/.bashrc if cap not found
    cap install STAGES=production
    
  3. Edit Capfile

  4. Capfile:

      require 'capistrano/rails'
      require 'capistrano/passenger'
      require 'capistrano/rbenv'
      set :rbenv_type, :user
      set :rbenv_ruby, '2.6.5'
    
  5. deploy.rb

      set :application, "my_site"
      set :repo_url, "/home/web/codes/rails"
      set :deploy_to, "/var/www/my_site"
      append :linked_files, 'config/database.yml', 'config/master.key'
      append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/system', 'public/uploads'
      set :keep_releases, 5
    
  6. deploy/production.rb

      server 'yourdomain.com', user: 'web', roles: %w{app db web}
    
  7. Prepare

    RAILS_ENV=production rails db:create # create db
    sudo mkdir /var/www/my_site
    sudo chown -R web:web /var/www/my_site
    cp master.key database.yml to /varw/www/my_site/shared/config
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys # Otherwise, ask for password when deploy
    
  8. Nginx config: /etc/nginx/site-available/default

    listen 80;
    listen [::]:80;
    server_name my_site.com;
    passenger_enabled on;
    rails_env    production;
    # Because of incorrect path in /etc/nginx/conf.d/mod-http-passenger.conf, we have to set it again here. It's optional if it's right above.
    #pssenger_ruby /home/web/.rbenv/shims/ruby; 
    root /var/www/my_site/current/public;
    
  9. Make swap, otherwise, too slow.

    cap production deploy
    

HTTPS

Install certbot
By snapd:

    sudo snap install core; sudo snap refresh core
    sudo apt-get remove certbot
    sudo snap install --classic certbot
    sudo ln -s /snap/bin/certbot /usr/bin/certbot

By APT:

    sudo apt-get install certbot python-certbot-nginx
    sudo certbot --nginx (choose direct, disable http)

usage:

    sudo certbot renew # for renew
    sudo certbot renew --webroot-path /var/www/xxx # renew with webroot path
    sudo certbot certonly -a webroot --webroot-path=/var/www/<your site>/current/public -d www.example.com -d example.com -d api.example.com.   # multiple sub-domain
    sudo certbot certificates # expiration day
    sudo certbot delete --cert-name # remove unused domain

It seems the auto cron will renew the certification once per two months. But Ngnix should be restarted to load the new file.

Basic

Generator

Config generator in application.rb

config.generators.test_framework false
config.generators do |g|
  # Disable jbuilder as we use JR
  # g.jbuilder        false
  # Disable empty files
  # helper files
  g.helper          false
  # assets files
  g.assets          false
end

compression

Javascript

  • jQuery: follow guide

    • install jquery if not yet: yarn add jquery
    • in config/webpack/environment.js
    const webpack = require('webpack')
    environment.plugins.prepend('Provide',
      new webpack.ProvidePlugin({
        $: 'jquery/src/jquery',
        jQuery: 'jquery/src/jquery'
      })
    )
    
    • in app/javascript/packs/application.js
    require('jquery')
    
    • check webpack-dev-server to make sure no error
  • support coffee files: follow guide

    • rails webpacker:install:coffee
      • updated config/webpack/environment.js
      • updated config/webpacker.yml
      • updated config/webpack/loaders/coffee.js
    • rm app/javascript/packs/hello_coffee.coffee
    • put coffee files in app/javascript/coffee
    • in application.js, add require('../coffee/application.coffee')

Bootstrap:

Guide

  1. Install

    yarn add bootstrap popper.js jquery
    
  2. In app/javascript/stylesheets/application.scss

    @import 'bootstrap/scss/bootstrap';
    
  3. In app/javascript/packs/application.js

    import 'stylesheets/application' # include scss above
    import 'bootstrap/dist/js/bootstrap';
    
  4. On-the-fly build for dev:

    bin/webpack-dev-server
    

Email

  1. Install rails g mailer admin_mailer send_passwd
  2. Allow less secure apps to access your Gmail account: Guide
  3. Email configuration for sending emails

    config.action_mailer.raise_delivery_errors = true
    config.action_mailer.delivery_method = :smtp
    config.action_mailer.smtp_settings = {
      :address              => "smtp.gmail.com",
      # NOTE: Please use 587 not 465. Details: https://github.com/rails/rails/issues/27298
      #:port                 => 465, # EOF error
      # Remember to enable less secure apps, otherwise Net::SMTPAuthenticationError
      :port                 => 587,
      :domain               => "my_site.com", # does it matter?
      :user_name            => "my_site@gmail.com",
      :password             => "my_password",
      # Plain vs Login, encry username and password together or separately.
      # Details: http://www.samlogic.net/articles/smtp-commands-reference-auth.htm
      #:authentication       => "plain",
      :authentication       => "login",
      :enable_starttls_auto => true
    }
    
  4. Check your email, Gmail may still block your access. You may need to use server to login your gmail account, then unlock, following the guide

    • NOTE: use ssh -Y in Mac to connect server, ssh -X not work

I18n

Guide

  1. add zh.yml file under lib/locale (default config/locales)
  2. config in config/initializers/locale.rb

    I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')]
    I18n.available_locales = [:en, :zh]
    I18n.default_locale = :zh
    
  3. In application.rb

    around_action :switch_locale
    def switch_locale(&action)
      locale = params[:locale] || I18n.default_locale
      I18n.with_locale(locale, &action)
    end
    def default_url_options
      { locale: I18n.locale }
    end
    
  4. config/routes.rb, put everything in

    scope "/:locale" do
      resources :books
    end
    

Google

Google analytics

  1. Register accounts
  2. Add js to head

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-159082166-1"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-159082166-1');
    </script>
    
  3. Add js to Rails, NOTE the hack for turbolinks

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <% if Rails.env.production? %>
      <script async src="https://www.googletagmanager.com/gtag/js?id=UA-159082166-1"></script>
      <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'UA-159082166-1');
        // turbolinks
        document.addEventListener('turbolinks:load', event => {
          if (typeof gtag === 'function') {
            gtag('config', 'UA-159082166-1', {
              'page_location': event.data.url
            });
          }
        });
      </script>
    <% end %>
    

Google recaptcha

  1. Get API key
  2. in Gemfile: gem "recaptcha"
  3. Configure keys in config/initializers/recaptcha.rb

    Recaptcha.configure do |config|
      config.site_key  = 'xxx'
      config.secret_key = 'xxxx'
    end
    
  4. Add to views: <%= recaptcha_tags %>

  5. Check in controller

    skip_verify = request.format.json?
    if (skip_verify || verify_recaptcha(model: @user)) && @user.save
      // OK
    else
      // ERROR
    end
    
Tag: