Integrating Jennifer & Amber v1.0+

Seth T.Seth T.
5 min read

Table of contents

To get the full experience with Jennifer, we'll first want to install sam. This is Jennifer's CLI tool that has generators for creating models, managing the db creation/resetting, migrations, etc. that aren't currently able to be added quickly and easily into the Amber CLI. So this gives users a way to still have the CLI conveniences of a framework. The nice part is that once sam is installed and working, this also means Amber will work.

First, add the sam shard to your shards.yml, it should be added under the "development dependencies" sections like this:

development_dependencies:
  ameba:
    github: crystal-ameba/ameba
    version: ~> 1.5.0
  sam:
    github: imdrasil/sam.cr
    version: ~> 0.5.0

Next, remove the entry for granite and citrine-i18n, and add the shards for Jennifer and your database adapter of choice. Your dependencies section should look like this on a brand new Amber app:

dependencies:
  amber:
    github: amberframework/amber
    version: 1.4.1 # Make sure to use the latest version of Amber here

  quartz_mailer:
    github: amberframework/quartz-mailer
    version: ~> 0.8.0

  jasper_helpers:
    github: amberframework/jasper-helpers
    version: ~> 1.2.2 

  jennifer:
    github: imdrasil/jennifer.cr
    version: "~> 0.13.0"

  pg:
    github: will/crystal-pg
    version: ~> 0.26.0

  # Uncomment to use MySQL. Note: on MySQL v8, this shard does not support the v8 authentication protocol, you'll want to run:
  # `mysql --default-auth=mysql_native_password` for MySQL to work properly
  #mysql:
    #github: crystal-lang/crystal-mysql
    #version: ~> 0.14.0

  # Uncomment to use sqlite
  #jennifer_sqlite3_adapter:
    #github: imdrasil/jennifer_sqlite3_adapter
    #version: "~> 0.4.0"

Save your shard.yml file at this point.

Next, create a new file in your projects root folder called override.shard.yml and save the following into the file:

i18n:
  github: crimson-knight/i18n.cr
  branch: master

You can now install your shards by running shards install.

You may get something like the warning below:

Shard "ameba" may be incompatible with Crystal 1.10.1

You can usually safely ignore this warning, or adjust the version down until the warning goes away. Eitherway, it's safe to move on.

Next, we are going to change the file contents of the config/database.cr file to the following:

require "jennifer"
require "jennifer/adapter/postgres" # for PostgreSQL
# require "jennifer/adapter/mysql" for MySQL
# require "jennifer_sqlite3_adapter" for SQLite

# This allows for easy test db use when running the `crystal spec` command
{% if @top_level.has_constant? "Spec" %}
  APP_ENV = "test"
{% else %}
  APP_ENV = ENV["APP_ENV"]? || "development"
{% end %}

Jennifer::Config.configure do |conf|
  conf.read("config/database.yml", APP_ENV)
  conf.from_uri(ENV["DATABASE_URI"]) if ENV.has_key?("DATABASE_URI")
  conf.pool_size = (ENV["DB_CONNECTION_POOL"] ||= "5").to_i
  conf.logger.level = APP_ENV == "development" ? Log::Severity::Debug : Log::Severity::Error
end

Next, we'll want to create the file containing our database connection details. This will look very similar to the database configuration in a Rails app, but don't be fooled! These are not identical :)

Create the file config/database.yml with the following contents, updated with your apps details. None of the databases need to be created yet, just put what you'd like your app databases to be called. If you use an existing database, it should still connect with the correct details.

default: &default
  host: localhost
  user: user_name # On Mac, this is the results from a fresh terminal session when you run `whoami`
  password: user_password # On Mac, this is blank by default, use empty quotes '' for this.
  adapter: postgres # or `mysql`, or `sqlite` without quotes

development:
  <<: *default
  db: application_database_name_development

test:
  <<: *default
  db: application_database_name_test

production:
  <<: *default
  db: application_database_name_production

Finally, we'll want to modify the sam.cr file found in your projects root after installation the shards.

The contents should look like this:

#!/bin/crystal

require "./config/database.cr" # here load jennifer and all required configurations
require "./db/migrations/*"
require "sam"
load_dependencies "jennifer"

# Here you can define your tasks
# desc "with description to be used by help command"
# task "test" do
#   puts "ping"
# end

You should now be able to run: crystal run sam.cr help from the projects root in your command line and see output something like this:

❯ jennifer_config crystal sam.cr help
Name                 Description
------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------
help               | Prints description for all tasks
generate:makefile  | Generates makefile extension. Now command could be executed via `make sam your:command argument`
generate:migration | Generates migration template. Usage - generate:migration <migration_name>
generate:model     | Generates model and migrations template. Usage - generate:model <ModelName>
db:migrate         | Will call all pending migrations
db:step            | Invoke next migration. Usage: db:step [<count>]
db:rollback        | Rollback migration. Usage: db:rollback [v=<migration_exclusive_version> | <count_to_rollback>]
db:drop            | Drops database
db:create          | Creates database
db:seed            | Populate database with default entities.
db:setup           | Runs db:create, db:migrate and db:seed
db:version         | Prints version of the last run migration
db:schema:load     | Loads database structure from the structure.sql file

If you've run into any errors, double check that you've saved all of the files with the most recent changes, and that there are no typos.

Important Note

Check in the src/ folder to see if there is already a models folder. As of Amber v1.4 the new command does not create this folder and this is the destination for models being created by generate:model.

Once you create the src/models folder, you should now be able to generate a model:

I like to build sam once and then re-run it. If you change anything in the sam.cr file, you'll need to recompile to pick up any changes outside of yml files.

crystal build sam.cr
./sam generate:model example_model name:string
./sam db:create
./sam db:migrate

Your database should now be setup and operational with basic generators for Jennifer working.

And, you're done! Your app should now work with Jennifer. The Amber CLI and sam don't yet work together, but the controller and view generators should get you very close to a working initial template with only minor changes to make your app compile.

Make sure to use same for creating/seeding/migrating your database.

0
Subscribe to my newsletter

Read articles from Seth T. directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Seth T.
Seth T.