diff --git a/.changes/unreleased/internal-20260120-083529.yaml b/.changes/unreleased/internal-20260120-083529.yaml new file mode 100644 index 0000000..4c1d6f0 --- /dev/null +++ b/.changes/unreleased/internal-20260120-083529.yaml @@ -0,0 +1,5 @@ +kind: internal +body: Cover more .embed_as scenarios in README +time: 2026-01-20T08:35:29.0036-03:00 +custom: + Issue: "15" diff --git a/README.md b/README.md index 0ddae0f..db482e8 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,15 @@ all the migration files from the filesystem and bundles them within the generated executable, removing the need to distribute them along your application. +The macro generates a method that returns a `Drift::Context` containing all the +bundled migrations. By default, it creates an **instance method**. To create a +**class method** instead, prepend `self.` to the method name. + +##### Basic usage (top-level) + +When used at the top level of your application, `embed_as` creates a method +you can call directly: + ```crystal require "sqlite3" require "drift" @@ -245,11 +254,64 @@ migrator.apply! db.close ``` -In the above example, `Drift.embed_as` created `my_migrations` method -bundling all the migrations found in `database/migrations` directory. +##### Usage within modules or classes + +When embedding migrations inside a module or class, use `self.` prefix to +create a class method. This allows you to call the method on the module/class +itself: + +```crystal +module MyApp::Database + Drift.embed_as("self.migrations", "database/migrations", dir: __DIR__) + + def self.migrate(db) + migrator = Drift::Migrator.new(db, migrations) + migrator.apply! + end +end + +# Usage: +db = DB.connect "sqlite3:app.db" +MyApp::Database.migrate(db) +``` + +Note the use of `dir: __DIR__` to resolve the migrations path relative to the +source file location rather than the current working directory. + +##### Using an abstract interface pattern + +For more complex applications, you can define an abstract interface that +multiple database classes can implement: + +```crystal +module MyApp::Migratable + abstract def context : Drift::Context + abstract def database : DB::Database + + def migrate + migrator = Drift::Migrator.new(database, context) + migrator.apply! + end +end + +class MyApp::MainDatabase + include MyApp::Migratable + + Drift.embed_as("context", "database/migrations", dir: __DIR__) + + def database : DB::Database + # return your database connection + end +end + +# Usage: +main_db = MyApp::MainDatabase.new +main_db.migrate +``` -When using classes or modules, you can also define instance or class methods -by prepending `self.` to the method name to use by Drift. +In this pattern, `embed_as` generates an instance method named `context` that +satisfies the abstract method requirement from `Migratable`. Each database class +can embed its own set of migrations while sharing the common migration logic. ## Contribution policy