Paste this code to create some basic starting application with authentication and other funny tools. I extensively use echo sed grep commands here.

give a man a fish and you feed him for a day. teach a man to fish and you feed him for a lifetime

RVM and other tools

If you do not have rails or git you need to install

gpg --keyserver hkp:// --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL | bash
rvm install 2.3.0
gem install bundle

sudo apt install git postgresql libpq-dev nodejs

Initial commit

You can choose database with rails param rails new myapp --database=postgresql but it is better to create .railsrc so it is used for all rails

cat >> ~/.railsrc << HERE_DOC
-d postgresql # use postgresql

Create new app

rails new myapp
# to specify version you can use
rails _5.2.1_ new myapp
cd myapp
rails db:create
git init . && git add . && git commit -m "rails new myapp"


bin/rails g migration enable_extension_for_uuid
# add following line to migration
  def change
    enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')

cat >> config/initializers/generators.rb << HERE_DOC
Rails.application.config.generators do |g|
  g.orm :active_record, primary_key_type: :uuid

Later, if you add some references, you need to specify type: :uuid like:

  t.references :post, type: :uuid, index: true

or error will be raised:

DETAIL:  Key columns "post_id" and "id" are of incompatible types: bigint and uuid.

Note that ordering by id, uuid is not possible. It is hard to implement on existing projects and on MySQL db.


cat >> .gitignore << 'HERE_DOC'
# vim temp files
# carrierwave upload files
# gedit files
# vagrant files
# byebug
# rspec temporary file
git commit -am "Update .gitignore"

Gemfile development & production tools

Some of the gems could be found on thoughtbot suspenders Paid 3th party service alternative for bullet is scoutapp, for exception_notification is sentry, informantapp.

cat >> Gemfile << HERE_DOC
group :development do
  # pretty print Ruby objects in full color
  gem 'awesome_print', require: 'ap'
  # static analysis security vulnerability scanner, run: `brakeman`
  gem 'brakeman', '~> 3.5.0', require: false
  # detect N+1 sql queries
  gem 'bullet'
  # detect out-of-date or vulnerable gems, run: `gemsurance`
  gem 'gemsurance'
  # automatic reload
  gem 'guard-livereload', require: false
  # open emails in browser
  gem 'letter_opener'
  # detect file changes
  gem 'listen', '~> 3.0.5'
  # support for Rails Panel - chrome extension
  gem 'meta_request'
  # debugger
  gem 'pry'
  gem 'pry-rails'
  # ruby static code analyzer
  gem 'rubocop', require: false
  # spring speeds up development by keeping your application running in the
  # background. Read more:
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'

Some not used gems

  # do not show assets in log\
  # gem "quiet_assets # can not find rails 5 version"\

  # irbtools includes interactive_editor gem (vim inside irb)\
  # just create ~/.irbrc with\
  # require "rubygems"\
  # require "irbtools"\
  gem "irbtools", require: "irbtools/binding"\

  # is not needed since rails will show line on which there is
  # exception (no need to insert console and use on web page).
  gem better_errors

  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'

  # config/application.rb
  # run with rails s -p b to allow local network, allow remote requests\
  config.web_console.whiny_requests = false'

Rubocop cli

rubocop --auto-correct # to autocorrent correct some files (except lineLength)
rubocop --auto-gen-config # generate .rubocop_todo.yml
echo 'inherit_from: .rubocop_todo.yml' > .rubocop.yml # create .rubocop.yml

Production gems and configurations

cat >> Gemfile << HERE_DOC
# adding vendor prefixes to css rules
gem "autoprefixer-rails"

# sets timezone based on browser timezone for each request
gem "browser-timezone-rails"

# need some js for timezone
cat >> app/assets/javascripts/application.js << HERE_DOC
//= require js.cookie
//= require jstz
//= require browser_timezone_rails/set_time_zone

guard init livereload
# gem suggest some old extension
# but there is new
# or you can use rack-livereload
# I receive error No such middleware to insert before: ActionDispatch::Static
# so better is to use browser plugin instead of gem 'rack-livereload'
# sed -i config/environments/development.rb -e '/^end/i \
#   # livereload\
#   # use rack-livereload or browser extension\
#   # if guard is not running, there is an error in js console:\
#   # Cross-origin plugin content from  must have a visible size larger than 400 x\
#   # 300 pixels, or it will be blocked. Invisible content is always blocked.\
#   config.middleware.insert_after ActionDispatch::Static, Rack::LiveReload\
# '

When I get error with command RAILS_ENV=production rails assets:precompile
 No such middleware to insert before: ActionDispatch::Static
Than solution is to add `gem 'rails_12factor`, group: :production`

cat > config/initializers/bullet.rb << HERE_DOC
if defined? Bullet
  Bullet.enable = true
  Bullet.alert = true
  Bullet.rails_logger = true

git add . && git commit -m "Adding guard and other useful gems"

# to run guard live reload, first increase max watches than just run guard
# echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo
sysctl -p
guard -d
# livereload debug with `guard -d`. Error if you also run it on another project
# there should not be eventmachine.rb:530:in `start_tcp_server': no acceptor (port is in use or requires root privileges) (RuntimeError)

Customize log output of rails logger in production with

Sample page

Button should we blue and Fa camera icon should be shown after installing bootstrap and fontawesome inside rails

rails g controller pages index --skip-helper --skip-assets --skip-controller-specs --skip-view-specs
echo '<button class="btn btn-primary">
  <i class="fa fa-camera-retro" aria-hidden="true"></i> fa-camera-retro</i>
' >> app/views/pages/index.html.erb
sed -i config/routes.rb -e '/draw/a \
  root "pages#index"'
git add . && git commit -m "Adding sample index page"
# initial scale on mobile devices
sed -i app/views/layouts/application.html.erb -e '/title/a \
    <meta name="viewport" content="width=device-width, initial-scale=1">'


npm install typeface-roboto
mkdir app/assets/stylesheets/plugins
cat >> app/assets/stylesheets/plugins << HERE_DOC
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  src: local('Roboto Regular'), local('Roboto-Regular'), asset-url('typeface-roboto/files/roboto-latin-400.woff') format('woff'), asset-url('typeface-roboto/files/roboto-latin-400.woff2') format('woff2');
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 500;
  src: local('Roboto Medium'), local('Roboto-Medium'), asset-url('typeface-roboto/files/roboto-latin-500.woff') format('woff'), asset-url('typeface-roboto/files/roboto-latin-500.woff2') format('woff2');
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 600;
  src: local('Roboto SemiBold'), local('Roboto-SemiBold'), asset-url('typeface-roboto/files/roboto-latin-500.woff') format('woff'), asset-url('typeface-roboto/files/roboto-latin-500.woff2') format('woff2');
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  src: local('Roboto Bold'), local('Roboto-Bold'), asset-url('typeface-roboto/files/roboto-latin-700.woff') format('woff'), asset-url('typeface-roboto/files/roboto-latin-700.woff2') format('woff2');

cat >> app/assets/stylesheets/application.sass << HERE_DOC
// plugins
@import 'plugins/roboto_font_face'

cat >> app/assets/stylesheets/common/body.sass << HERE_DOC
  font-family: 'Roboto', sans-serif

Twitter bootstrap Gem

Adding flash (both from server and client)

You can use text-center bootstrap helper (ie text-align: center;). Also the collors

sed -i app/views/layouts/application.html.erb -e '/yield/c \
  <div class="text-center">\
    <span class="notice text-success" id="notice"></span>\
    <span class="alert text-danger" id="alert"></span>\
    <%=raw "flash_message(document.getElementById('notice'), '#{j notice}');" if notice %>\
    <%=raw "flash_message(document.getElementById('alert'), '#{j alert}');" if alert %>\
    <%= yield %>\

cat > app/assets/javascripts/main.js.erb << 'HERE_DOC'
var FLASH_DURATION = 5000;
function flash_appear(element, message, i) {
  if (i == undefined)
    i = 0;
  element.innerText = message.substring(0,i);
    if (i<message.length)
      flash_appear(element, message, i+1);
function flash_dissapear(element, message, i) {
  if (message == undefined)
    message = element.innerText;
  if (i == undefined)
    i = message.length-1;
  element.innerText = message.substring(0,i);
    if (i>0)
      flash_dissapear(element, message,i-1);

function flash_message(element, message) {
  flash_appear(element, message);
  setTimeout(function(){ flash_dissapear(element); }, FLASH_DURATION);
git add . && git commit -m "Adding flash to layout"

Bourbon css mixins

echo '
# css mixin library
gem "bourbon", '~> 5.0.0.beta' # bourbon 5 is requred by bitters 1.3
gem "neat"
' >> Gemfile
echo '
@import "bourbon";
@import "base/base"; // this is
@import "neat";
' > app/assets/stylesheets/application.scss
git rm app/assets/stylesheets/application.css

gem install bitters
cd app/assets/stylesheets && bitters install
sed -i '/grid-settings/c @import "grid-settings";' base/_base.scss
cd -

git add . && git commit -m "Adding bourbon, neat and bitters scss"


sed -i Gemfile -e '/group :development do/a  \
  # slim templating\
  gem "slim-rails"'

gem install html2slim
erb2slim app/views/leads/index.html.erb


For various ways of integrating Angular look at angular-and-ruby-on-rails

Simplify secrets and add smtp credentials

YML file can use anchor (&) and reference (*) so you do not repeat the code. When you use reference * (as for testing) you can not add or update keys, but with << you can (as for production) (more on get syntax right) Note that you can use default values for env variables but only for those strings. Do not use boolean since <%= ENV['MY_VAR'} || true %> will always resolve to true. Instead of this

development: &default
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] || 'some_secret' %>

test: *default
  <<: *default
  monitor_mode: true

In rails 5 there are shared key which will use all stuff.

cat > config/secrets.yml << HERE_DOC
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] || 'some_secret' %>

  # sending emails
  smtp_username: <%= ENV["SMTP_USERNAME"] %>
  smtp_password: <%= ENV["SMTP_PASSWORD"] %>

  # for all outgoing emails
  mailer_sender: <%= ENV["MAILER_SENDER"] || "My Company <>" %>

  # default_url is required for links in email body or in links in controller
  # when url host is not available (for example rails console)
    host: <%= ENV["DEFAULT_URL_HOST"] || (Rails.env.production? ? "" : "localhost") %>
    port: <%= ENV["DEFAULT_URL_PORT"] || (Rails.env.development? ?[:Port] : nil) %>

# `shared` is automatically included, no need to write
# shared: &default
# development: *default
# or
# development:
#   <<: *default

git add . && git commit -m "Simplify secrets"

Basic mail settings

We can generate application mailer with:

rails generate mailer UserMailer hello
git add . && git commit -am "rails generate mailer UserMailer hello"

Change default from address:

sed -i app/mailers/application_mailer.rb -e '/default/c \
  default from: Rails.application.secrets.mailer_sender'

Set default url option, that is domain for root_url:

# if you need to get from rails 4 use { port:[:Port] }
# in config/environments/development.rb and also include
# require 'rails/commands/server` on the top of the file

# for rails 5 you can use[:Port] and no need to
# require anything, but it works only if you provide -p param to rails s

# config/application.rb
    link = Rails.application.secrets.default_url.symbolize_keys
    # for link urls in emails
    config.action_mailer.default_url_options = link
    # for link urls in rails console
    config.after_initialize do
      Rails.application.routes.default_url_options = link
    # for asset-url or img_tag in emails
    config.action_mailer.asset_host = "http://#{link[:host]}:#{link[:port]}"

For devise you need to set default sender:

# devise
sed -i config/initializers/devise.rb -e '/mailer_sender/c \
  config.mailer_sender = Rails.application.secrets.mailer_sender'

For local development use Letter opener:

sed -i '/group :development do/a  \
  # open emails in browser\
  gem "letter_opener"' Gemfile
sed -i '/^end$/i \  config.action_mailer.delivery_method = :letter_opener' config/environments/development.rb 
bundle && git add . && git commit -m "Letter opener to see emails in browser"
rails runner UserMailer.hello.deliver

For production see send and receive emails in rails

Skip generators

sed -i '/Rails::Application/a \
    config.i18n.enforce_available_locales = true\
    config.generators do |generate|\
      generate.helper false\
      generate.javascript_engine false\
      generate.request_specs false\
      generate.routing_specs false\
      generate.stylesheets false\
      generate.test_framework :rspec\
      generate.view_specs false\
    config.action_controller.action_on_unpermitted_parameters = :raise\
' config/application.rb
git add . && git commit -m "Skip generators"


Cleareance gem

Clearance is simple email authorization. It could work with facebook auth but it’s designed to be only email auth.

echo "gem 'clearance'" >> Gemfile && bundle
rails generate clearance:install
rake db:migrate
rails generate clearance:routes
git add . && git commit -m "rails g clearance:install"

sed -i '/<body>/a \\n\
    <% if signed_in? %>\
      <%= %>\
      <%= button_to "Sign out", sign_out_path, method: :delete %>\
    <% else %>\
      <%= link_to "Sign in", sign_in_path %>\
    <% end %>\
' app/views/layouts/application.html.erb
git add . && git commit -m "Adding sign signout path"

Company scaffold with skipped unused files

rails g scaffold company name:string user:references --no-stylesheets --no-fixture --no-test-framework --no-helper --no-assets --no-jbuilder
sed -i '/companies/a \  root "companies#index"' config/routes.rb
rake db:migrate && git add . && git commit -m "rails g scaffold company name:string user:references"


Puma is now default webserver on rails. But by default it runs in single mode WEB_CONCURRENCY=1 so on heroku it will allow RAILS_MAX_THREADS connections if GIL is not trigered. You can simulate slow connection with sleep 10, it does not triggel GIL.

curl $u/action_with_sleep_10 &
curl $u/action_with_sleep_10 &
# real 10s
# real 20s

curl $u/action_with_sleep_10 &
curl $u/action_with_sleep_10 &
# real 10s
# real 10s

You can follow heroku article

cat >> Gemfile <<HERE_DOC
gem 'puma'

# Rails 5 puma is default, and config/puma.rb is used, so do not need Procfile
# but is it advisable to write it and put rakek db:migrate so you do not need to
# run migration after you deploy. Restart is not needed as it was needed after
# heroku run rake db:migrate (there are no exception, but update was not
# actually saved in new columns, so restart was needed)
cat >> Procfile <<HERE_DOC
web: bundle exec puma -C config/puma.rb
release: rake db:migrate

cat >> config/puma.rb <<HERE_DOC
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count


rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  # See:

# on development always use single mode
mkdir config/puma
cat >> config/puma/development.rb <<HERE_DOC
workers 0

Heroku deploy

If you need to run separate command for background jobs, you need to write Procfile.

export MYAPP_NAME=my-app # only dash, not underscore
# # postgresql on production
# sed -i Gemfile -e "/gem 'sqlite3/c \
# gem 'pg'"
# sed -i '/adapter: sqlite3/c \  adapter: postgresql' config/database.yml
# sed -i "/development.sqlite3/c \  database: ${MYAPP_NAME}_dev" config/database.yml
# sed -i "/test.sqlite3/c \  database: ${MYAPP_NAME}_test" config/database.yml
# sed -i "/production.sqlite3/c \  database: ${MYAPP_NAME}_prod" config/database.yml
# rails in production use: production: url: <%= ENV['DATABASE_URL'] %>

cat >> Gemfile << HERE_DOC
# heroku uses this 12 factor gem
gem 'rails_12factor', group: :production
git commit -am "Heroku uses 12factor gem"

heroku apps:create $MYAPP_NAME
heroku addons:create heroku-postgresql:hobby-dev # this will set DATABASE_URL
git push heroku master --set-upstream

heroku run rake db:migrate db:seed
# heroku run rake db:setup will raise error:
# PG::ConnectionBad: FATAL:  permission denied for database "postgres"
# DETAIL:  User does not have CONNECT privilege
# try
# heroku pg:reset --confirm $MYAPP_NAME
# heroku restart
# I do not know how to drop db since db:migrate:reset does not work either

# sometimes you need to recompile assets when you change secrets but assets are
# not changed, and you need to purge cache, install plugin
# heroku plugins:install heroku-repo
# heroku repo:purge_cache

heroku open

Heroku use ubuntu 16 or Ubuntu 18, you can change

heroku apps:info
heroku stack
heroku stack:set heroku-16

You can pull from heroku databse You need to find the name of heroku database by clicking on Postgresl plugin

rails db:drop
heroku pg:pull postesql-name-on-heroku my_rails_app_development

# also pushing
heroku pg:reset
heroku pg:push buyers_development postgresql-animate-86842

If you need to provision new database (upgrade from free to hobby) than you can use pg copy

heroku config # find color of old database
heroku addons:destroy HEROKU_POSTGRESQL_NAVY_URL

If you need to compile node packages than you need need custom buildpack. We could use 3th party gulp buildpacks but default node buildpack works fine.

There is also for mysql or

devDependencies need to be renamed to dependecies since it runs node production mode (I tried to disable production mode using NPM_CONFIG_ONLY but than other thinks does not work). Imporant is NODE_MODULES_CACHE. If we (by default) cache /node_modules it will not build new version to public folder.

# deploy to heroku
heroku buildpacks:set
heroku buildpacks:add --index 1

heroku buildpacks # should return  1. nodejs  2. ruby (latest wins :)
# alternativelly, we can define then in file .buildpacks
# echo '
# ' > .buildpacks
# heroku config:add BUILDPACK_URL=
git rm -rf public
echo '/public
/node_modules' >> .gitignore
git add .gitignore
git commit -m "Remove public folder from git repo"

echo '{
  "name": "rootApp",
  "scripts": {
  "dependencies": {
    "myappAngular": "file:./client"
  "cacheDirectories": [
' > package.json
git add package.json && git commit -m "Add package.json for nodejs buildpack detect"

cd client
sed -i "/dist: 'dist/c \  dist: '../../public'," gulp/conf.js
sed -i '/"scripts":/a \    "postinstall": "bower install && gulp build",' package.json
sed -i '/"devDependencies":/c \  "dependencies": {\
    "bower": "*",' package.json
git add . && git commit -m "Configure postinstall gulp build"
cd ..

git push heroku
heroku config # NPM_CONFIG_PRODUCTION=true NODE_ENV=production NODE_MODULES_CACHE=true
heroku open
# usefull command to test is `npm install`
# git commit --amend --allow-empty --no-edit && echo "output is saved: cat log/heroku.log" && git push heroku -f > log/heroku.log 2>&1 && heroku run bash -c 'mysql -v'

On heroku add Papertrail add-on and go to the and search for “Started GET” , save and create email alert or add internal notification For custom domain just add on settings your domain name and create CNAME record for www with value If you need to match all subdomains (wildcard), you can put Domain Name * and CNAME record for * with same value If you need to add root domain (naked, bare, zone apex) than you can’t use loopia but some other suggested domain name providers.

Deploy javascript npm required tasks

Heroku dyno puma settings Some Things in system = arrival rate X time spent in system so for server it is: hequests_in_system = requests per second X average_response_time (115 req/s * 0.147s = 16 request in system, so we need at leat 16 workers in same time). utilization = requests_in_system / how_many_workers for example = 115 req/s X 147ms response / 45 workers = 37%

Use 3 WEB_CONCURRENCY workers and 3-5 RAILS_MAX_THREADS (not more since each thread need connection to database, and use some on memory). suggests 2-4 workers sleep also do not lock GIL (so all threads are working).

On MRI, there is a Global Interpreter Lock (GIL) that ensures only one thread can be run at any time. IO operations such as database calls, interacting with the file system, or making external http calls will not lock the GIL. Most Rails applications heavily use IO, so adding additional threads will allow Puma to process multiple threads, gaining you more throughput. `

Also increase database, redis and memcached connections. Heroku postgresql hobby-basic has limit of 20 connections (enought for 3x5=15)

Google app engine

It is not hard to deploy to google ap engine