---
title: Marten 0.4.0 release notes
pagination_prev: null
pagination_next: null
---

_January 13, 2024._

## Requirements and compatibility

Crystal 1.9, 1.10, and 1.11.

## New features

### Generators

Marten now provides a generator mechanism that makes it easy to create various abstractions, files, and structures within an existing project. This feature is available through the use of the [`gen`](../../development/reference/management-commands.md#gen) management command and facilitates the generation of key components such as [models](../../models-and-databases/introduction.md), [schemas](../../schemas/introduction.md), [emails](../../emailing/introduction.md), or [applications](../../development/applications.md). The [authentication application](../../authentication/introduction.md) can now also be added easily to existing projects through the use of generators. By leveraging generators, developers can improve their workflow and speed up the development of their Marten projects while following best practices.

Below are highlighted some examples illustrating the use of the [`gen`](../../development/reference/management-commands.md#gen) management command:

```sh
# Generate a model in the admin app:
marten gen model User name:string email:string --app admin

# Generate a new TestEmail email in the blog application:
marten gen email TestEmail --app blog

# Add a new 'blogging' application to the current project:
marten gen app blogging

# Add the authentication application to the current project:
margen gen auth
```

You can read more about the generator mechanism in the [dedicated documentation](../../development/generators.md). All the available generators are also listed in the [generators reference](../../development/reference/generators.md).

### Multi table inheritance

It is now possible to define models that inherit from other concrete models (ie. non-abstract models). In this situation, each model can be used/queried individually and has its own associated database table. The framework automatically defines a set of "links" between each model that uses multi table inheritance and its parent models in order to ensure that the relational structure and inheritance hierarchy are maintained.

For example:

```crystal
class Person < Marten::Model
  field :id, :big_int, primary_key: true, auto: true
  field :first_name, :string, max_size: 100
  field :last_name, :string, max_size: 100
end

class Employee < Person
  field :company_name, :string, max_size: 100
end

employee = Employee.filter(first_name: "John").first!
employee.first_name # => "John"
```

All the fields defined in the `Person` model can be accessed when interacting with records of the `Employee` model (despite the fact that the data itself is stored in distinct tables).

You can read more about this new kind of model inheritance in [Multi table inheritance](../../models-and-databases/introduction.md#multi-table-inheritance).

### Schema handler callbacks

Handlers that inherit from the base schema handler - [`Marten::Handlers::Schema`](pathname:///api/0.4/Marten/Handlers/Schema.html) - or one of its subclasses (such as [`Marten::Handlers::RecordCreate`](pathname:///api/0.4/Marten/Handlers/RecordCreate.html) or [`Marten::Handlers::RecordUpdate`](pathname:///api/0.4/Marten/Handlers/RecordUpdate.html)) can now define new kinds of callbacks that allow to easily manipulate the considered [schema](../../schemas/introduction.md) instance and to define logic to execute before the schema is validated or after (eg. when the schema validation is successful or failed):

* [`before_schema_validation`](../../handlers-and-http/callbacks.md#before_schema_validation)
* [`after_schema_validation`](../../handlers-and-http/callbacks.md#after_schema_validation)
* [`after_successful_schema_validation`](../../handlers-and-http/callbacks.md#after_successful_schema_validation)
* [`after_failed_schema_validation`](../../handlers-and-http/callbacks.md#after_failed_schema_validation)

For example, the [`after_successful_schema_validation`](../../handlers-and-http/callbacks.md#after_successful_schema_validation) callback can be used to create a flash message after a schema has been successfully validated:

```crystal
class ArticleCreateHandler < Marten::Handlers::Schema
  success_route_name "home"
  template_name "articles/create.html"
  schema ArticleSchema

  after_successful_schema_validation :generate_success_flash_message

  private def generate_success_flash_message : Nil
    flash[:notice] = "Article successfully created!"
  end
end
```

Please head over to [Schema handler callbacks](../../handlers-and-http/callbacks.md#schema-handler-callbacks) to learn more about these new types of callbacks.

### URL field for models and schemas

It is now possible to define `url` fields in [models](../../models-and-databases/reference/fields.md#url) and [schemas](../../schemas/reference/fields.md#url). These allow you to easily persist valid URLs in your models but also to expect valid URL values in data validated through the use of schemas.

For example:

```crystal
class User < Marten::Model
  field :id, :big_int, primary_key: true, auto: true
  field :website_url, :url, blank: true, null: true
end
```

### Slug field for models and schemas

It is now possible to define `slug` fields in [models](../../models-and-databases/reference/fields.md#slug) and [schemas](../../schemas/reference/fields.md#slug). These allow you to easily persist valid slug values (ie. strings that can only include characters, numbers, dashes, and underscores) in your models but also to expect such values in data validated through the use of schemas.

For example:

```crystal
class User < Marten::Model
  field :id, :big_int, primary_key: true, auto: true
  field :username, :slug
end
```

### Minor features

#### Models and databases

* Support for removing records from many-to-many fields was added and many-to-many field query sets now provide a [`#remove`](pathname:///api/0.4/Marten/DB/Query/ManyToManySet.html#remove(*objs%3AM)%3ANil-instance-method) helper method allowing to easily remove specific records from a specific relation. You can learn more about this capability in [Many-to-many relationships](../../models-and-databases/relationships.md#many-to-many-relationships).
* Support for clearing all the references to records targeted by many-to-many fields was added. Indeed, many-to-many field query sets now provide a [`#clear`](pathname:///api/0.4/Marten/DB/Query/ManyToManySet.html#clear%3ANil-instance-method) method allowing to easily clear a specific relation. You can learn more about this capability in [Many-to-many relationships](../../models-and-databases/relationships.md#many-to-many-relationships).
* It is now possible to specify arrays of records to add or remove from a many-to-many relationship query set, through the use of the [`#add`](pathname:///api/0.4/Marten/DB/Query/ManyToManySet.html#add(*objs%3AM)-instance-method) and [`#remove`](pathname:///api/0.4/Marten/DB/Query/ManyToManySet.html#remove(*objs%3AM)%3ANil-instance-method) methods. See the [related documentation](../../models-and-databases/relationships.md#interacting-with-related-records-2) to learn more about interacting with records targeted by many-to-many relationships.
* Records targeted by reverse relations that are contributed to models by [`one_to_one`](../../models-and-databases/reference/fields.md#one_to_one) (ie. when using the [`related`](../../models-and-databases/reference/fields.md#related-2) option) are now memoized when the corresponding methods are called on related model instances.
* Relation fields that contribute methods that return query sets to models (such as [`many_to_one`](../../models-and-databases/reference/fields.md#many_to_one) or [`many_to_many`](../../models-and-databases/reference/fields.md#many_to_many) fields) now make sure that those query set objects are memoized at the record level. The corresponding instance variables are also reset when the considered records are reloaded. This allows to limit the number of queries involved when iterating multiple times over the records targeted by a [`many_to_many`](../../models-and-databases/reference/fields.md#many_to_many) field for example.
* The [`#order`](../../models-and-databases/reference/query-set.md#order) query set method can now be called directly on model classes to allow retrieving all the records of the considered model in a specific order.
* A [`#pk?`](pathname:///api/0.4/Marten/DB/Model/Table.html#pk%3F%3ABool-instance-method) model method can now be leveraged to determine if a primary key value is set on a given model record.
* The [`#join`](../../models-and-databases/reference/query-set.md#join) query set method now makes it possible to pre-select one-to-one reverse relations. This essentially allows to traverse a [`one_to_one`](../../models-and-databases/reference/fields.md#one_to_one) field back to the model record on which the field is specified.
* The [`#count`](../../models-and-databases/reference/query-set.md#count) query set method can now take an optional field name to count the number of records that have a non-null value for the corresponding column in the database.

#### Handlers and HTTP

* It is now optional to define a name for included route maps (but defining a name for individual routes that are associated with [handlers](../../handlers-and-http/introduction.md) is still mandatory). You can read more about this in [Defining included routes](../../handlers-and-http/routing.md#defining-included-routes).
* The [`Marten::Handlers::Schema`](pathname:///api/0.4/Marten/Handlers/Schema.html) generic handler now allows modifying the schema object context name through the use of the [`#schema_context_name`](pathname:///api/0.4/Marten/Handlers/Schema.html#schema_context_name(name%3AString|Symbol)-class-method) method.
* It is now possible to specify symbol status codes when making use of the [`#respond`](../../handlers-and-http/introduction.md#respond), [`#render`](../../handlers-and-http/introduction.md#render), [`#head`](../../handlers-and-http/introduction.md#head), and [`#json`](../../handlers-and-http/introduction.md#json) response helper methods. Such symbols must comply with the values of the [`HTTP::Status`](https://crystal-lang.org/api/HTTP/Status.html) enum.
* The hash of matched routing parameters that is available from handlers through the use of the `#params` method can accept symbols and strings when performing key lookups.
* The [GZip middleware](../../handlers-and-http/reference/middlewares.md#gzip-middleware) now incorporates a mitigation strategy against the BREACH attack. This strategy (described in the [Heal The Breach paper](https://ieeexplore.ieee.org/document/9754554)) involves introducing up to 100 random bytes into GZip responses to enhance the security against such attacks.
* A new [`before_render`](../../handlers-and-http/callbacks.md#before_render) callback type is now available to handlers. Such callbacks are executed before rendering a [template](../../templates/introduction.md) in order to produce a response. As such they are well suited for adding new variables to the global template context so that they are available to the template runtime.
* All handlers now have access to a [global template context](../../handlers-and-http/introduction.md#global-template-context) through the use of the [`#context`](pathname:///api/0.4/Marten/Handlers/Base.html#context-instance-method) method. This template context object is available for the lifetime of the considered handler and can be mutated to define which variables are made available to the template runtime when rendering templates (either through the use of the [`#render`](../../handlers-and-http/introduction.md#render) helper method or when rendering templates as part of subclasses of the [`Marten::Handlers::Template`](../../handlers-and-http/generic-handlers.md#rendering-a-template) generic handler). This feature can be combined with the [`before_render`](../../handlers-and-http/callbacks.md#before_render) callback to effortlessly introduce new variables to the context used for rendering a template and generating a handler response.

#### Templates

* A [`with`](../../templates/reference/tags.md#with) template tag was introduced in order to make it easy to assign one or more variables inside a template block.
* A [`time`](../../templates/reference/filters.md#time) template tag was introduced in order to make it possible to output the string representation of a time variable according to a specific [time format pattern](https://crystal-lang.org/api/Time/Format.html).
* An [`escape`](../../templates/reference/filters.md#escape) template tag was introduced in order to make it easy to explicitly escape [safe strings](../../templates/introduction.md#auto-escaping) in templates.
* The ability to configure how undefined/unknown variables are treated was added to the framework: by default, such variables are treated as `nil` values (so nothing is displayed for such variables, and they are evaluated as falsey in if conditions). This behavior can be configured via the [`templates.strict_variables`](../../development/reference/settings.md#strict_variables) setting, and you can learn more about it in [Strict variables](../../templates/introduction.md#strict-variables).

#### Development

* The [`new`](../../development/reference/management-commands.md#new) management command now accepts an optional `--database` option that can be used to preconfigure the application database (eg. `--database=postgresql`).
* A [`clearsessions`](../../development/reference/management-commands.md#clearsessions) management command was introduced in order to ease the process of clearing expired session entries.
* Custom management commands can now define how they want to handle unknown or undefined arguments through the use of the [`#on_unknown_argument`](pathname:///api/0.4/Marten/CLI/Manage/Command/Base.html#on_unknown_argument(%26block%3AString->)-instance-method) method. This can be leveraged to implement management commands which can accept a variable number of positional arguments.
* Custom management commands can now define how they want to handle invalid options through the use of the [`#on_invalid_option`](pathname:///api/0.4/Marten/CLI/Manage/Command/Base.html#on_invalid_option(%26block%3AString->)-instance-method) method.

#### Emailing

* [Emails](../../emailing/introduction.md) now provide a set of [callbacks](../../emailing/callbacks.md) that make it easy to define logic that is triggered at different stages of an email's lifecycle (before/after an email gets delivered, before rendering the email's template).

#### Authentication

* The generated authentication application now features the ability to change the password of the currently logged-in user.

## Backward incompatible changes

### Handlers and HTTP

* Custom [session stores](../../handlers-and-http/sessions.md#session-stores) must now implement a [`#clear_expired_entries`](pathname:///api/0.4/Marten/HTTP/Session/Store/Base.html#clear_expired_entries%3ANil-instance-method) method (allowing to clear expired session entries if this is applicable for the considered store).
* The introduction of the [global template context](../../handlers-and-http/introduction.md#global-template-context) involves that generic handlers that used to override the `#context` method (in order to insert record or schema objects into the template context for example) now leverage [`before_render`](../../handlers-and-http/callbacks.md#before_render) callbacks in order to mutate the global context and define the same variables. Generic handler subclasses that were overriding this `#context` method and calling `super` in it will likely need to be updated in order to leverage the [`before_render`](../../handlers-and-http/callbacks.md#before_render) callback to add custom variables to the [global template context](../../handlers-and-http/introduction.md#global-template-context).

### Templates

* The [`default`](../../templates/reference/filters.md#default) template filter will now return the specified default value if the incoming value is falsey or empty.

### Emailing

* The introduction of the [global template context](../../emailing/introduction.md#modifying-the-template-context) involves that emails that used to explicitly define a `#context` method (eg. in order to define a hash of template variables from local instance variables) won't work anymore. Instead these emails should now leverage the [`before_render`](../../emailing/callbacks.md#before_render) callback in order to [add these variables to the email template context object](../../emailing/introduction.md#modifying-the-template-context).
