V2.2: Upgrade to 2.2
These notes cover an upgrade from 2.1 to 2.2.
Update the app
-
Edit
Gemfileand update the versions of the Hanami gems to"~> 2.2". -
Remove
gem "guard-puma"from yourGemfile(this is now a dependency of hanami-reloader). -
Update
spec/spec_helper.rband update anyrequireorrequire_relativelines for files inspec/support/with the following:
# frozen_string_literal: true
require "pathname"
SPEC_ROOT = Pathname(__dir__).realpath.freeze
# <leave main file contents here>
SPEC_ROOT.glob("support/**/*.rb").each { |f| require f }
Add database support
Certain steps below apply to each of your app and slices. Where the code examples use Bookshelf as a name, replace this with the relevant name for your app or slice.
- Add the following gems to your
Gemfile:
gem "hanami-db", "~> 2.2"
# If you want a SQLite database
gem "sqlite3"
# If you want a Postgres database
gem "pg"
# If you want a MySQL database
gem "mysql2"
group :test do
gem "database_cleaner-sequel"
end
- Add the following lines to
.gitignore:
db/*.sqlite
-
If you’re going to use a SQLite database, run
mkdir db -
Add a
.envwith aDATABASE_URLand check it into source control:
# This is checked into source control, so put sensitive values into `.env.local`
# For a SQLite database
DATABASE_URL=sqlite://db/bookshelf.sqlite
# For a Postgres database
DATABASE_URL=postgres://localhost/bookshelf
# For a MySQL database
DATABASE_URL=mysql2://root@localhost/bookshelf
-
Create a
config/db/migrate/dir and put a.keepfile within it. -
Create a
config/db/seeds.rb:
# This seeds file should create the database records required to run the app.
#
# The code should be idempotent so that it can be executed at any time.
#
# To load the seeds, run `hanami db seed`. Seeds are also loaded as part of `hanami db prepare`.
# For example, if you have appropriate repos available:
#
# category_repo = Hanami.app["repos.category_repo"]
# category_repo.create(title: "General")
#
# Alternatively, you can use relations directly:
#
# categories = Hanami.app["relations.categories"]
# categories.insert(title: "General")
- Add a
db/relation.rb(toapp/or your slice):
# frozen_string_literal: true
require "hanami/db/relation"
module Bookshelf
module DB
class Relation < Hanami::DB::Relation
end
end
end
- Add a
db/repo.rb(toapp/or your slice):
# frozen_string_literal: true
require "hanami/db/repo"
module Bookshelf
module DB
class Repo < Hanami::DB::Repo
end
end
end
- Add a
db/struct.rb(toapp/or your slice):
# frozen_string_literal: true
require "hanami/db/struct"
module Bookshelf
module DB
class Struct < Hanami::DB::Struct
end
end
end
-
Create a
relations/dir (insideapp/or your slice) and put a.keepfile within it. -
Create a
repos/dir (insideapp/or your slice) and put a.keepfile within it. -
Create a
structs/dir (insideapp/or your slice) and put a.keepfile within it. -
Create
spec/support/db.rb:
# frozen_string_literal: true
# Tag feature spec examples as `:db`
#
# See support/db/cleaning.rb for how the database is cleaned around these `:db` examples.
RSpec.configure do |config|
config.define_derived_metadata(type: :feature) do |metadata|
metadata[:db] = true
end
end
- Create
spec/support/db/cleaning.rb:
# frozen_string_literal: true
require "database_cleaner/sequel"
# Clean the databases between tests tagged as `:db`
RSpec.configure do |config|
# Returns all the configured databases across the app and its slices.
#
# Used in the before/after hooks below to ensure each database is cleaned between examples.
#
# Modify this proc (or any code below) if you only need specific databases cleaned.
all_databases = -> {
slices = [Hanami.app] + Hanami.app.slices.with_nested
slices.each_with_object([]) { |slice, dbs|
next unless slice.key?("db.rom")
dbs.concat slice["db.rom"].gateways.values.map(&:connection)
}.uniq
}
config.before :suite do
all_databases.call.each do |db|
DatabaseCleaner[:sequel, db: db].clean_with :truncation, except: ["schema_migrations"]
end
end
config.before :each, :db do |example|
strategy = example.metadata[:js] ? :truncation : :transaction
all_databases.call.each do |db|
DatabaseCleaner[:sequel, db: db].strategy = strategy
DatabaseCleaner[:sequel, db: db].start
end
end
config.after :each, :db do
all_databases.call.each do |db|
DatabaseCleaner[:sequel, db: db].clean
end
end
end
Add operations
Certain steps below apply to each of your app and slices. Where the code examples use Bookshelf as a name, replace this with the relevant name for your app or slice.
- Add the following gem to your
Gemfile:
gem "dry-operation"
- Add an
operation.rb(toapp/or your slice):
# auto_register: false
# frozen_string_literal: true
require "dry/operation"
module Bookshelf
class Operation < Dry::Operation
end
end
- Create
spec/support/operations.rb:
# frozen_string_literal: true
require "dry/monads"
RSpec.configure do |config|
# Provide `Success` and `Failure` for testing operation results
config.include Dry::Monads[:result]
end