Sinatra

Default folder for partials is views/ and name is with .erb extension. Default layout file is views/layout.erb. Always use symbols when referencing templates, event with subfolder erb :'subdir/home'. Instance variables are accessible in templates. Static files are server from public/ folder. For stylesheet use scss :stylesheet, style: :expanded For coffescript coffee :index

# to change default views folder
set :views, settings.root + '/templates'

Filter can be used to modify request and response, set instance variable.

before '/protected/*' do
  authenticate!
end

Session and other configuration options

require 'securerandom'

enable :sessions
set :session_secret, ENV.fetch('SESSION_SECRET') { SecureRandom.hex(64) }

# to be able to access from other computers, or run with `ruby app.rb -o 0.0.0.0
set :bind, '0.0.0.0'

get '/:value' do
  session['val'] = params['value']
end

Redirect with redirect to('/foo?bar=42'). Cache-control header is set with cache_control :public. Rack cache can be used for caching.

Top level application assumes a micro app style configuration (a single app file, public and views folders). If you want modular style (run is disabled by default) you can inherit from Sinatra::Base (logging and inline templates disabled by default). If you want similar to classic style, you can write with:

require 'sinatra/base'

class MyApp < Sinatra::Application
  get '/' do
    'Hello world!'
  end
end
# config.ru
require './app'
run MyApp

Run with

bundle exec rackup -p- 4567

Sinatra Contrib

http://sinatrarb.com/contrib/

Reloading in Sinatra can be done with rerun http://sinatrarb.com/faq.html or with

require 'sinatra/reloader' if development?

Sinatra book

http://sinatra-org-book.herokuapp.com/

Logger

Inside get actions you can define helper and use request logger

get '/' do
  logger.info 'get_root'
end

For use in templates you can define helpers

helpers do
  def logger
    request.logger
  end
end

To enable logging to a file use as well to stdout. Problem is that I do not see custom logs with logger.info params

# http://recipes.sinatrarb.com/p/middleware/rack_commonlogger
configure do
  # logging is enabled by default in classic style applications,
  # so `enable :logging` is not needed
  # create folder `mkdir log` and gitignore with `touch log/.keep`
  file = File.new("#{settings.root}/log/#{settings.environment}.log", 'a+')
  file.sync = true
  use Rack::CommonLogger, file
end

For use in other places you can create global variable (I do not know how to access logger outside of actions). But the problem here is that I do not see messages in file (but see in STDOUT on developemnt) when I use $logger.info but logger.info inside actions works fine.

# https://stackoverflow.com/questions/5995854/logging-in-sinatra
configure :production do
  $logger = Logger.new('log/common.log', 'hourly')
  $logger.level = Logger::WARN

  # Spit stdout and stderr to a file during production
  # in case something goes wrong
  $stdout.reopen("log/#{settings.environment}.log", 'w')
  $stdout.sync = true
  $stderr.reopen($stdout)
end

configure :development do
  $logger = Logger.new(STDOUT)
end

https://github.com/minodes/sinatra-logger

Enviroments

APP_ENV=production ruby my_app.rb
# or
ruby my_app.rb -e production

Sinatra Sass

To add support to scss you can add gem 'sass' and if using modular style

# config.ru
require 'sass/plugin/rack'

Sass::Plugin.options[:style] = :compressed
use Sass::Plugin::Rack

or is using classis style, run

sass --watch public/assets/stylesheets/sass:public/assets/stylesheets

and include in layout

<link rel="stylesheet" href="/assets/stylesheets/switch.css">

Activerecord

https://github.com/janko-m/sinatra-activerecord

# Gemfile
gem 'sinatra-activerecord'
gem 'sqlite3'
gem 'rake'

# app.rb
require 'sinatra/activerecord'
set :database, adapter: 'sqlite3', database: "#{__dir__}/db/home_automation.sqlite3"

# Rakefile
require 'sinatra/activerecord/rake'

namespace :db do
  task :load_config do
    require './app'
  end
end

Note that we use __dir__ to get app_file folder so it works fine when we run the app from non root path ruby some/path/to/app.rb

And you can create tables

rake db:create_migration NAME=create_temperatures

and models

class Temperature < ActiveRecord::Base
end

On raspberri pi you should install sqlite3

sudo apt-get autoremove; sudo apt-get autoclean;sudo apt-get clean
sudo apt-get update; sudo apt-get -y dist-upgrade; sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev

Sinatra tests

https://www.sitepoint.com/build-sinatra-api-using-tdd-heroku-continuous-integration-travis/

Console

You can access console like rails c with https://github.com/sickill/racksh

Webpack

You can use javascript with hot reloading using https://github.com/kopylovvlad/sinatra-webpack-vuejs-template

Sending emails

# Gemfile
gem 'mail'

# my_mail.rb
require 'mail'

# test with
# rvmsudo ruby -e "load 'my_mail.rb';MyMail.send()"
# using sudo requires -E to pass enviroment variables
# sudo -E ruby -e "load 'my_mail.rb';MyMail.send()"

GMAIL_EMAIL = ENV['GMAIL_EMAIL'] # ENV['rvm_EMAIL_USER_NAME'],
GMAIL_PASSWORD = ENV['GMAIL_PASSWORD'] # ENV['rvm_EMAIL_PASSWORD'],
EXCEPTION_RECIPIENTS = ENV['EXCEPTION_RECIPIENTS'] # ENV['rvm_EMAIL_RECIPIENT_EMAIL']

options = {
  address: 'smtp.gmail.com',
  port: 587,
  user_name: GMAIL_EMAIL,
  password: GMAIL_PASSWORD,
}
# puts options

Mail.defaults do
  delivery_method :smtp, options
end

module MyMail
  def self.send(subject: 'alert', text: 'hi', attachment: nil)
    puts "Send email #{text} #{attachment}"
    Mail.deliver do
      to EXCEPTION_RECIPIENTS
      from GMAIL_EMAIL
      subject subject
      body text
      add_file attachment unless attachment.nil?
    end
  rescue StandardError => e
    puts "MyMail.send failed #{e}"
  end
end

Usage in app.rb is like

MyMail.send attachment: image_file, text: S3.getUrl(video_file)

Timezone

In pure ruby, you can show UTC time in your time zone by specifying offset

 Time.now.localtime("+02:00")

Examples of opensource apps

  • https://github.com/swanson/stringer Nice Sinatra ActiveRecord Backbone app. It
  • https://lbrito1.github.io/blog/2020/02/repurposing-android.html Running sinatra on mobile phone

Backbone

https://backbonejs.org/