Why you should try Amber Framework

Published Jan 21, 2018Last updated Feb 20, 2018
Why you should try Amber Framework

As web developers, we all have flirted with the idea of having the perfect web framework — one that is fun to work with, does not get in your way, catches bugs early, is easy to scale, easy to learn, deployable anywhere and adaptable to different architecture patterns without sacrificing performance.

Amber takes an aim to address these qualms by leveraging on Crystal Language and converging a series of widely accepted features.

Amber is a web application framework written in Crystal, which makes building web applications fast, simple, and enjoyable with blazing fast performance.
Here are a few good reasons to give it a try:

1. Crystal Language

Crystal as a programming language offers a high-level syntax with the performance and characteristics of a low-level language.

  • Syntax — Write a program with highly expressive, yet more simplistic code that is easy to read without scarifying performance.
  • Type System — Statically type-checked, so any type errors will be caught early by the compiler rather than fail on run-time. Fewer bugs.
  • Null Reference Checks — All types are non-nilable in Crystal, and nilable variables are represented as a union between the type and nil. Again, fewer bugs.
  • Macros— Crystal’s answer to meta-programming is a powerful macro system, which ranges from basic template to Abstract Syntax Tree inspection.
  • Concurrency Model — Crystal uses green threads, called fibers, to achieve concurrency. Fibers communicate with each other using channels, as in Go or Clojure, without having to turn to shared memory or locks.

2. Extremely low learning curve

Amber is very easy to learn and pick up, with a friendly and easy to read Ruby-like syntax. Amber shares the same concepts as other popular web application frameworks that you find in other languages like Ruby, Express, Elixir and Laravel, making it easy to understand and familiar to work with.
3. Blazing fast performance

Amber is for programmers who want more performance, who enjoy working in a high-level scripting environment, with combine native execution speed and concurrency, without sacrificing joy in programming because of code complexity.

02:28:43 Request | Started 2018-01-07 14:28:43 - 05:00
02:28:43 Request | Status: 200  Method: GET Pipeline: web Format: html
02:28:43 Request | Requested Url: /
02:28:43 Request | Time Elapsed: 94.0µs

4. Convergence of features

Amber developers did not stop with Crystal features. Amber converges a wide range of accepted features from a broad series of web frameworks, especially with Ruby On Rails.

Controllers

Amber does not re-invent the wheel. It keeps you in familiar territory by embracing Model-View-Controller patterns and Convention over Configuration principles.

class UsersController < ApplicationController
  # Filters are methods that are run "before", "after" a controller action.
  before_action do
    # runs for specified actions
    only [:index, :world, :show] { increment(1) }
    # runs for all actions
    all { increment(1) }
  end

  after_action do
    # runs for specified actions
    only [:index, :world] { increment(1) }
  end
  
  def index
    @users = Users.all
    render("index.slang")
  end
end

Views Templates

Amber supports a wide range of template languages. There are 4 different template languages currently supported: Slang, ECR, Mustache, and Temel.

Since Crystal is a compiled language, all view templates are pre-compiled. At run-time, all templates are loaded into memory. There are no disk reads, complex file caching, or template engine computation involved, allowing your pages to render swiftly.

doctype html
html
  head
    meta name="viewport" content="width=device-width,initial-scale=1.0"
    title This is a title
    css:
      h1 {color: red;} 
      p {color: green;}
    style h2 {color: blue;}
  body
    ul 
     - @users.each do |user|
       li = "#{user.name} - #{user.email}"

Pipelines

A pipeline is a series of transformations throughout the request life-cycle. Each request interacts with a “pipe” at every step of the request. This differs from other HTTP middleware layers, where the request and response are separated in the stack.

Amber::Server.configure do |app|
  pipeline :web, :auth do
    plug Amber::Pipe::Logger.new
    plug Amber::Pipe::Flash.new
    plug Amber::Pipe::Session.new
    plug Amber::Pipe::CSRF.new
  end
  
  pipeline :auth do
    plug Authenticate.new
  end
end

Parameters Validation

One of the most important aspects of validation is to prevent the widespread issue of invalid persisted data in programs.

Parameters Validation is your first line of defense. We can set a series of data correctness rules for a given controller-action. This allows for the separation of controller-action validation from model validation, by invalidating the request at an early stage preventing the execution of more demanding operations.

update_params = params.validation do
  required(:name, "Your First Name is missing!") { |p| p.name? & !p.name.empty? }
  required(:email, "Your email address is invalid!") { |p| p.email? & p.size.between? 1..10 }
  required(:last_name) { |p| p.last_name? }
end

Routing

Amber defines routes explicitly in one central file. With the routes.cr file, it is easy to understand at a high level which transformations are being performed for each controller-action.

Routes can be scoped to a particular path. This is quite useful for representing: API versions, CMS, Admin areas, etc.

Web-sockets routes represents a full duplex communication channel over a TCP connection with low overhead, facilitating real-time data transfer form and to the Amber server.

routes :web, "/pages" do
  get "/about", StaticController, :about
  resources "/posts", PostController
  websocket "/chat", ChatSocket
end

Channels

All web-socket messages are routed through channels. A channel represents a topic. Clients subscribe to a Topic send and receive new messages. Channels define 3 public methods:

- **handle_joined** - Called when a user joins a channel.
- **handle_message** - Called when a user sends a message to a channel. A common message handler will simply rebroadcast the message to the other subscribers with rebroadcast! method.
- **handle_leave** - Called when a user leaves the channel.
class HomeController < ApplicationController
  def index
    ChatSocket.broadcast("message", "chat_room:123", "message_new", {"message" => "A new visitor!"})
    render("index.slang")
  end
end

Object-Relational Mapping Agnostic

Amber model layer is not tied to any specific object-relational mapping library Instead it provides a default active record pattern ORM called Granite::ORM, for quick prototyping.

The developer is free to configure and use any of the Crystal available Object-Relational Mapping library available: Granite, Crecto, Jennifer, Lucky::Record, Active Record. This allows you to select the right tool for your project, without Amber get in your way.

require "granite_orm/adapter/sqlite"

class Comment < Granite::ORM::Base
  adapter sqlite
  
  has_many :posts

table_name comments
  field name : String
  field body : String

validate("Invalid Comment.", ->(comment : self) {
    (comment.name != nil && comment.name != "") || (comment.body != nil && comment.body != "")
  })
end

# Querying

# ORDER BY Example
posts = Post.all("ORDER BY created_at DESC")

# JOIN Example
posts = Post.all("JOIN comments c ON c.post_id = post.id
                  WHERE c.name = ?
                  ORDER BY post.created_at DESC",
                  ["Joe"])

Amber CLI

Amber has a built in CLI tool, to make your life easier while developing applications.

Here is a list of the available commands:

d, deploy — Provisions server and deploys project.
db, database — Performs database maintenance tasks
e, encrypt — Encrypts environment YAML file. [env | -e — editor | — noedit]
x, exec — Executes Crystal code within the application scope
g, generate — Generate Amber classes (Controller, Migrations, Views, Models, Mailer, etc)
n, new — Generates a new Amber project
routes — Prints all defined application routes
w, watch — Starts amber development server and rebuilds on file changes

System Tests

Amber was built with testing in mind. Amber made it as simple as possible to and provides a built in System Test framework that runs consistently and fast.

class SomeFeature < GarnetSpec::System::Test
  scenario "user visits amber framework and sees getting started button" do
    visit "http://www.amberframework.org"
    timeout 1000
    click_on(:css, "header a.btn.btn-primary")
    wait 2000
    element(:tag_name, "body").text.should contain "Introduction"
  end
end

5. Fast Prototyping and Scalability

Web application performance and Scalability are of huge importance when developing a business around internet services especially when we talk about driving more traffic, engagement, and increase brand loyalty. What’s more is slow downs and/or downtime can cost companies thousands of dollar.

Amber has some benefits to overcome these issues:

  • Global type inference. You can program without type annotations except for a few cases where you are required to do so (generic type arguments). Amber still recommends to use types
  • Amber allow for very quick prototyping, similar to dynamic languages. You can scaffold a project in 7 steps without touching one line of code.
  • Amber gives you a high throughput with with no premature optimizations, and sub second response times. Thanks to Crystal, Amber has a low consumption of CPU, Memory, and disk space.
  • Distributed binary — All amber projects compile to a binary that can be easily distributed. This makes deployments fast and easy.
  • Catch bugs early. Programs are verified by before they can be executed. This rules out many programming errors Null reference checks to name one.

Where to start?

What you’ve seen here just barely scratches the surface of what Amber Framework can do. There’s so much more to help you build, organize, and scale your web applications. To start coding yourself, I’ll recommend following resources.

Lastly I must thank the Crystal and Amber Community for your support and contributions.

Discover and read more posts from Elias Perez
get started