### Provider with Prepare, Start, and Stop Lifecycle Source: https://hanakai.org/learn/dry/dry-system/v1.2/providers A comprehensive provider example demonstrating setup (`prepare`), runtime usage (`start`), and cleanup (`stop`) phases. It configures a database connection and manages its lifecycle. ```ruby # system/providers/db.rb Application.register_provider(:database) do prepare do require 'third_party/db' register(:database, ThirdParty::DB.configure(ENV['DB_URL'])) end start do container[:database].establish_connection end stop do container[:database].close_connection end end ``` -------------------------------- ### Create bin/setup Script for Development Environment Source: https://hanakai.org/learn/hanami/v2.3/upgrade-notes A `bin/setup` script automates development environment setup, including bundle install, npm install, and database preparation. Ensure it is executable (`chmod +x bin/setup`). ```bash #!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' # This script is a way to set up and keep your development environment updated # automatically. It is meant to be idempotent so that you can run it at any # time to get the same result. Add any new necessary setup steps to this file # as your application evolves. announce() { local bold='\033[1m' local reset='\033[0m' printf "${bold}${1}${reset}\n" } announce "Running bundle install..." bundle check || bundle install announce "\nRunning npm install..." npm install announce "\nPreparing the database..." hanami db prepare announce "\n🌸 Setup complete!" ``` -------------------------------- ### Full Example: Setup, Repository, and Usage Source: https://hanakai.org/learn/rom/v5.0/repositories/reading-simple-objects Demonstrates setting up a ROM container, defining a user relation and repository with selector methods, and then using these methods to query and retrieve data. ```ruby require 'rom-repository' rom = ROM.container(:sql, 'sqlite::memory') do |config| config.default.connection.create_table(:users) do primary_key :id column :name, String, null: false column :email, String, null: false end config.relation(:users) do schema(infer: true) end end class UserRepo < ROM::Repository[:users] def query(conditions) users.where(conditions).to_a end def by_id(id) users.by_pk(id).one! end # ... etc end user_repo = UserRepo.new(rom) ``` ```ruby # assuming that there is already data present user_repo.query(first_name: 'Malcolm', last_name: 'Reynolds') #=> [ROM::Struct[User] , ROM::Struct[User], ...] user_repo.by_id(1) #=> {id: 1, first_name: 'Malcolm', last_name: 'Reynolds'} ``` -------------------------------- ### Hanami Development Server Output Example Source: https://hanakai.org/learn/hanami This is an example of the output you can expect when the Hanami development server starts successfully. It indicates that the web and assets processes have started. ```text 08:14:33 web.1 | started with pid 56242 08:14:33 assets.1 | started with pid 56243 08:14:34 assets.1 | [gsg_app] [watch] build finished, watching for changes... 08:14:34 web.1 | 08:14:34 - INFO - Using Guardfile at /Users/tim/Source/scratch/gsg_app/Guardfile. 08:14:34 web.1 | 08:14:34 - INFO - Puma starting on port 2300 in development environment. 08:14:34 web.1 | 08:14:34 - INFO - Guard is now watching at '/Users/tim/Source/scratch/gsg_app' 08:14:35 web.1 | Puma starting in single mode... 08:14:35 web.1 | * Puma version: 6.4.2 (ruby 3.3.0-p0) ("The Eagle of Durango") 08:14:35 web.1 | * Min threads: 5 08:14:35 web.1 | * Max threads: 5 08:14:35 web.1 | * Environment: development 08:14:35 web.1 | * PID: 56250 08:14:35 web.1 | * Listening on http://0.0.0.0:2300 08:14:35 web.1 | * Starting control server on http://127.0.0.1:9293 08:14:35 web.1 | * Starting control server on http://[::1]:9293 08:14:35 web.1 | Use Ctrl-C to stop ``` -------------------------------- ### Registering a Basic Provider Source: https://hanakai.org/learn/dry/dry-system/v1.2/providers Define a provider to manage a component. The `prepare` block is for setup and requiring third-party code, while `start` registers the component with the container. ```ruby # system/providers/persistence.rb Application.register_provider(:database) do prepare do require "third_party/db" end start do register(:database, ThirdParty::DB.new) end end ``` -------------------------------- ### Start Hanami Console Source: https://hanakai.org/learn/hanami/v2.3/cli-commands/console Starts the Hanami console (REPL) for your application. The prompt indicates the current environment. ```bash $ bundle exec hanami console bookshelf[development]> ``` -------------------------------- ### Install Hanami Gem Source: https://hanakai.org/learn/hanami/v2.3/getting-started Install the Hanami gem to begin creating Hanami applications. ```bash $ gem install hanami ``` -------------------------------- ### Start the Hanami Development Server Source: https://hanakai.org/learn/hanami/v2.3/getting-started Run the `hanami dev` command within your project directory to start the development server and asset watcher. ```bash $ bundle exec hanami dev ``` -------------------------------- ### Options Example Source: https://hanakai.org/learn/dry/dry-cli/v1.1 Illustrates the use of named options passed after the command and arguments. ```bash $ foo generate test generated tests - framework: minitest ``` ```bash $ foo generate test --framework=rspec generated tests - framework: rspec ``` ```bash $ foo generate test --framework=unknown ERROR: "foo generate test" was called with arguments "--framework=unknown" ``` -------------------------------- ### Setup ROM Container with SQL and Relations Source: https://hanakai.org/learn/rom/v5.0/repositories/writing-aggregates Configures an in-memory SQLite database, defines `users` and `tasks` tables with a foreign key, and establishes `has_many` and `belongs_to` associations between them. This setup is required before defining repositories. ```ruby require 'rom-repository' rom = ROM.container(:sql, 'sqlite::memory') do |config| config.default.create_table(:users) do primary_key :id column :name, String, null: false column :email, String, null: false end config.default.create_table(:tasks) do primary_key :id foreign_key :user_id, :users column :title, String, null: false end config.relation(:users) do schema(infer: true) do associations do has_many :tasks end end end config.relation(:tasks) do schema(infer: true) do associations do belongs_to :user end end end end ``` -------------------------------- ### Execute Command with Callbacks Source: https://hanakai.org/learn/dry/dry-cli/v1.1/callbacks Example output showing the execution of the 'hello' command with both 'before' and 'after' callbacks active. ```bash $ foo hello Anton debug: {:name=>"Anton"} hello Anton bye, Anton ``` -------------------------------- ### Define a complete CLI application with dry-cli Source: https://hanakai.org/learn/dry/dry-cli/v1.1 This example demonstrates how to define multiple commands, arguments, options, and nested commands within a dry-cli application. It includes version, echo, start, stop, exec, and completion commands, along with a nested 'generate' command. ```ruby #!/usr/bin/env ruby require "bundler/setup" require "dry/cli" module Foo module CLI module Commands extend Dry::CLI::Registry class Version < Dry::CLI::Command desc "Print version" def call(*) puts "1.0.0" end end class Echo < Dry::CLI::Command desc "Print input" argument :input, desc: "Input to print" example [ " # Prints 'wuh?'", "hello, folks # Prints 'hello, folks'" ] def call(input: nil, **) if input.nil? puts "wuh?" else puts input end end end class Start < Dry::CLI::Command desc "Start Foo machinery" argument :root, required: true, desc: "Root directory" example [ "path/to/root # Start Foo at root directory" ] def call(root:, **) puts "started - root: #{root}" end end class Stop < Dry::CLI::Command desc "Stop Foo machinery" option :graceful, type: :boolean, default: true, desc: "Graceful stop" def call(**options) puts "stopped - graceful: #{options.fetch(:graceful)}" end end class Exec < Dry::CLI::Command desc "Execute a task" argument :task, type: :string, required: true, desc: "Task to be executed" argument :dirs, type: :array, required: false, desc: "Optional directories" def call(task:, dirs: [], **) puts "exec - task: #{task}, dirs: #{dirs.inspect}" end end class Completion < Dry::CLI::Command desc "Generate completion" option :shell, default: "bash", values: %w[bash zsh] def call(shell:, **) puts "generated completion - shell: #{shell}" end end module Generate class Configuration < Dry::CLI::Command desc "Generate configuration" option :apps, type: :array, default: [], aliases: ["-a"], desc: "Generate configuration for specific apps" def call(apps:, **) puts "generated configuration for apps: #{apps.inspect}" end end class Test < Dry::CLI::Command desc "Generate tests" option :framework, default: "minitest", values: %w[minitest rspec] def call(framework:, **) puts "generated tests - framework: #{framework}" end end end register "version", Version, aliases: ["v", "-v", "--version"] register "echo", Echo register "start", Start register "stop", Stop register "exec", Exec register "completion", Completion, hidden: true register "generate", aliases: ["g"] do |prefix| prefix.register "config", Generate::Configuration prefix.register "test", Generate::Test end end end end Dry::CLI.new(Foo::CLI::Commands).call ``` -------------------------------- ### Starting a Specific Provider Source: https://hanakai.org/learn/dry/dry-system/v1.2/providers You can start a specific provider and access its registered components. This is useful for testing or when only a subset of the application's components is needed. ```ruby # system/application/container.rb class Application < Dry::System::Container configure do |config| config.root = Pathname("/my/app") end end Application.start(:database) # and now `database` becomes available Application["database"] ``` -------------------------------- ### PostgreSQL Quick Connect Source: https://hanakai.org/learn/rom/v5.0/sql A quick configuration example for connecting to a PostgreSQL database using a connection string and an options hash. ```ruby opts = { username: 'postgres', password: 'postgres', encoding: 'UTF8' } config = ROM::Configuration.new(:sql, 'postgres://localhost/database_name', opts) ``` -------------------------------- ### Quick Connect with MySQL2 Source: https://hanakai.org/learn/rom/v5.0/sql Example of configuring a ROM connection for MySQL2 with specific options like encoding. ```ruby opts = { encoding: 'UTF8' } config = ROM::Configuration.new(:sql, 'mysql2://localhost/database_name', opts) ``` -------------------------------- ### Install Hanami Dependencies Source: https://hanakai.org/learn/hanami/v2.3/cli-commands/install Execute this command to install third-party dependencies and Hanami gems. It's usually run automatically by `hanami new`. ```bash $ bundle exec hanami install ``` -------------------------------- ### Basic Logger Setup Source: https://hanakai.org/learn/dry/dry-logger/v1.1 Configure a basic logger that outputs to $stdout. The logger is initialized with a program name. ```ruby logger = Dry.Logger(:my_app) logger.info "Hello World" # Hello World ``` -------------------------------- ### Start Hanami App in Development Mode Source: https://hanakai.org/learn/hanami/v2.3/cli-commands/dev Execute this command in your terminal to start the Hanami application in development mode. ```bash $ bundle exec hanami dev ``` -------------------------------- ### Custom 'enqueue' Step Adapter Example Source: https://hanakai.org/learn/dry/dry-transaction/v0.16/custom-step-adapters An example of a custom 'enqueue' step adapter that simulates pushing an operation into a background queue. It returns the input wrapped in a `Success` monad. ```ruby QUEUE = [] class MyStepAdapters < Dry::Transaction::StepAdapters register :enqueue, -> step, input, *args { # In a real app, this would push the operation into a background worker queue QUEUE << step.operation.call(input, *args) Dry::Monads.Success(input) } end class CreateUser include Dry::Transaction(container: Container, step_adapters: MyStepAdapters) step :create enqueue :send_welcome_email end ``` -------------------------------- ### Generated Singleton Resource Routes Source: https://hanakai.org/learn/hanami/v2.3/routing This is an example of the routes generated by `resource :profile`. ```text GET /profile profile.show GET /profile/new profile.new POST /profile profile.create GET /profile/edit profile.edit PATCH /profile profile.update DELETE /profile profile.destroy ``` -------------------------------- ### Example Usage: Greeting with Name and Age Source: https://hanakai.org/learn/dry/dry-cli/v1.1/arguments Demonstrates calling the `greet` command with both the required `name` and optional `age` arguments. ```bash $ foo greet Luca 35 Hello, Luca. You are 35 years old. ``` -------------------------------- ### Command Aliases Example Source: https://hanakai.org/learn/dry/dry-cli/v1.1 Illustrates the use of command aliases for shorter invocation. ```bash $ foo version 1.0.0 ``` ```bash $ foo v 1.0.0 ``` ```bash $ foo -v 1.0.0 ``` ```bash $ foo --version 1.0.0 ``` -------------------------------- ### Array Options Example Source: https://hanakai.org/learn/dry/dry-cli/v1.1 Shows how to use array options, which are named arguments that accept multiple comma-separated values. ```bash $ foo generate config --apps=web,api generated configuration for apps: ["web", "api"] ``` -------------------------------- ### Render Partial Example Source: https://hanakai.org/learn/dry/dry-view/v0.8/templates Demonstrates how to render a partial named 'sidebar' within a template. ```html <%= render :sidebar %> ``` -------------------------------- ### Start Hanami Console Source: https://hanakai.org/learn/hanami/v2.3/getting-started/building-an-api Launch the interactive console for your Hanami application to interact with the database. ```bash $ bundle exec hanami console ``` -------------------------------- ### Execute Command with Specified Option Source: https://hanakai.org/learn/dry/dry-cli/v1.1/options This example demonstrates executing the command and providing a valid value for the `--mode` option. ```bash $ foo request --mode=http2 Performing a request (mode: http2) ``` -------------------------------- ### Subcommands Example Source: https://hanakai.org/learn/dry/dry-cli/v1.1 Lists available subcommands for a given command. Subcommands are nested commands. ```bash $ foo generate Commands: foo generate config # Generate configuration foo generate test # Generate tests ``` -------------------------------- ### Subcommand Aliases Example Source: https://hanakai.org/learn/dry/dry-cli/v1.1 Demonstrates aliases for subcommands, providing shorter ways to invoke nested commands. ```bash $ foo g config generated configuration for apps: [] ``` -------------------------------- ### Example Asset Directory Structure Source: https://hanakai.org/learn/hanami/v2.3/assets Illustrates the directory structure for multiple entry points, showing the location of compiled CSS and JavaScript bundles. ```plaintext app/assets β”œβ”€β”€ css β”‚ β”œβ”€β”€ app.css β”‚ └── login β”‚ └── app.css β”œβ”€β”€ images β”‚ └── favicon.ico └── js β”œβ”€β”€ app.js # Entry point └── login β”œβ”€β”€ app.js # Entry point └── resetPassword.js ``` -------------------------------- ### Example Usage: Greeting with Name Only Source: https://hanakai.org/learn/dry/dry-cli/v1.1/arguments Demonstrates calling the `greet` command with only the required `name` argument. ```bash $ foo greet Luca Hello, Luca. ``` -------------------------------- ### Executing Account Command with Specified Format Source: https://hanakai.org/learn/dry/dry-cli/v1.1/commands-with-subcommands-and-params This example demonstrates executing the 'account' command and providing the 'long' format argument. ```bash $ foo account long # Information about account in long format. ``` -------------------------------- ### Executing Account Subcommand Source: https://hanakai.org/learn/dry/dry-cli/v1.1/commands-with-subcommands-and-params This example shows how to execute the 'users' subcommand of the 'account' command. ```bash $ foo account users # Information about account users. ``` -------------------------------- ### Boolean Options Example Source: https://hanakai.org/learn/dry/dry-cli/v1.1 Demonstrates boolean options, which act as flags to change command behavior. ```bash $ foo stop stopped - graceful: true ``` ```bash $ foo stop --no-graceful stopped - graceful: false ``` -------------------------------- ### Booting and Inspecting a Slice Container Source: https://hanakai.org/learn/hanami/app/slices This example shows how to boot a specific slice and inspect its available components using the Hanami console. It demonstrates accessing and calling a query from the slice's container. ```ruby bundle exec hanami console bookshelf[development]> API::Slice.boot => API::Slice bookshelf[development]> API::Slice.keys => ["settings", "actions.countries.show", "queries.countries.show", "inflector", "logger", "notifications", "rack.monitor", "routes"] bookshelf[development]> API::Slice["queries.countries.show"].call("UA") => {:name=>"Ukraine", :flag=>"πŸ‡ΊπŸ‡¦", :currency=>"UAH"} ``` -------------------------------- ### Conditional Auto-registration Source: https://hanakai.org/learn/dry/dry-system/v1.2/component-dirs Use a proc with `auto_register` to conditionally enable or disable auto-registration based on component properties. This example excludes components starting with 'entities'. ```ruby config.component_dirs.add "lib" do |dir| dir.auto_register = proc do |component| !component.identifier.start_with?("entities") end end ``` -------------------------------- ### Example Using All Meta Tokens Source: https://hanakai.org/learn/dry/dry-logger/v1.2/templates Demonstrates a template that includes all standard meta tokens: time, progname, severity, message, and payload. This provides a detailed log entry. ```ruby logger = Dry.Logger(:my_app, template: "%