V2.2: Upgrade to 2.2
These notes cover an upgrade from 2.1 to 2.2.
Update the app
-
Edit
Gemfile
and 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.rb
and update anyrequire
orrequire_relative
lines 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
.env
with aDATABASE_URL
and 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.keep
file 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.keep
file within it. -
Create a
repos/
dir (insideapp/
or your slice) and put a.keep
file within it. -
Create a
structs/
dir (insideapp/
or your slice) and put a.keep
file 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