I will probably start a series of open-source Ruby Projects. Maybe I will call it #opensource #Friday.
Zammad is an open-source ticketing system, that also offers an on-cloud product.
They have their product open-sourced on Github and it is built using (at the moment of writing this article) Ruby 3.1.3 and Rails 7
The license is GNU AGPL
They mention on their website why they chose to make the product open source:
Each file in the repository has a license line like:
Some ideas from the open-source repo
I don't have enough time to analyse in depth the repo. So just looking around for 30 minutes, here are some things that I extracted
rails stats returned the following:
They use Rubocop with extra cops added. They require some cops provided by gems and custom cops written by them:
require: - rubocop-capybara - rubocop-factory_bot - rubocop-faker - rubocop-graphql - rubocop-inflector - rubocop-performance - rubocop-rails - rubocop-rspec - ../config/initializers/inflections.rb - ./rubocop_zammad.rb
rubocop_zammad.rb they are loading custom cops from
Here are some custom cops written by them:
Checking if the migration file starts with a valid timestamp
Checking usages of
find_byto check if an Active Record exists and replace it with
Checking that the only allowed
default_scopeis about simple ordering
Checking for using
Checking usages of
.to_symon strings and change to
Checking usages of
unlessand suggest using
Checking copyright notice and adding it when missing
More about their style guide can be found at
They appear to use 3 DBs, each one having their group. One (the activerecord-nulldb-adapter) is actually a NullObject pattern implemented for Active Record.
Based on the loaded connection they do a preflight check in an initializer. This is what it looks like:
Rails.application.config.after_initialize do Zammad::Application::Initializer::DbPreflightCheck.perform end
and you can go check
lib/zammad/application/initializer to see what kind of checks are executed for each adapter.
This is a way to make sure that the actual DB server respects a contract they have defined in these initializers (e.g. what extensions are activated or config defaults or minimum version).
See this example of a check for MySQL from the same file:
Some gems used
argon2 - "A Ruby gem offering bindings for Argon2 password hashing"
rszr - "Rszr is an image resizer for Ruby based on the Imlib2 library. It is faster and consumes less memory than MiniMagick, GD2 and VIPS, and comes with an optional drop-in interface for Rails ActiveStorage image processing"
biz - "Time calculations using business hours"
diffy - "It provides a convenient way to generate a diff from two strings or files. Instead of reimplementing the LCS diff algorithm Diffy uses battle tested Unix diff to generate diffs, and focuses on providing a convenient interface, and getting out of your way"
chunky_png - "ChunkyPNG is a pure Ruby library to read and write PNG images and access textual metadata. It has no dependency on RMagick, or any other library for that matter"
localhost - "This gem provides a convenient API for generating per-user self-signed root certificates"
activerecord-nulldb - "NullDB is the Null Object pattern as applied to ActiveRecord database adapters. It is a database backend that translates database interactions into no-ops. Using NullDB enables you to test your model business logic - including after_save hooks - without ever touching a real database"
The main method that a Service object should define is
execute but there is no enforcement of this. It is just that everything under app/services/service has this method defined.
All the logic about GraphQL is inside app/graphql, namescoped to
And all jobs have a default priority of 200 while low_priority is defined as being 300
There are probably a lot more interesting things to discover about the codebase but this is what I got in a short review.
Enjoyed this article?