Marten 0.6.0 release notes
Under development.
Requirements and compatibility
- Crystal: 1.14, 1.15, and 1.16.
- Databases:
- MariaDB 10.5 and higher.
- MySQL 8.0.11 and higher.
- PostgreSQL 14 and higher.
- SQLite 3.31.0 and higher.
New features
Localized routes
Marten now provides the ability to define localized routes through the use of two mechanisms: automatically adding locale prefixes to routes and activating the appropriate locale based on the prefix, and translating the routes themselves. These mechanisms can be used independently or in combination.
For example, the following routes map defines routes that will be prefixed by the currently activated locales and whose paths will be translated using the considered project's translations:
ARTICLE_ROUTES = Marten::Routing::Map.draw do
path t("routes.articles.list"), ArticlesHandler, name: "list"
path t("routes.articles.create"), ArticleCreateHandler, name: "create"
path t("routes.articles.detail"), ArticleDetailHandler, name: "detail"
path t("routes.articles.update"), ArticleUpdateHandler, name: "update"
path t("routes.articles.delete"), ArticleDeleteHandler, name: "delete"
end
Marten.routes.draw do
localized do
path t("routes.landing"), LandingPageHandler, name: "landing"
path t("routes.articles.prefix"), ARTICLE_ROUTES, name: "articles"
end
end
As highlighted above, the use of routes prefixed with locales can be activated by wrapping route paths by a call to the #localized
method. Route path translations can be defined using the #t
method, which assigns a translation key to each route (this key is then dynamically used to generate the route's path based on the active locale).
With the routes map defined above, generated routes are fully localized and vary based on the currently activated locale:
I18n.activate("en")
Marten.routes.reverse("landing") # => "/en/landing"
Marten.routes.reverse("articles:create") # => "/en/articles/create"
I18n.activate("fr")
Marten.routes.reverse("landing") # => "/fr/accueil"
Marten.routes.reverse("articles:create") # => "/fr/articles/creer"
Please refer to Localized routes to learn more about this new capability.
Array schema field
Marten now lets you define array
schema fields that allow validating lists of values, with each value subject to the validation rules of an array member field (such as string
, int
, or any other existing schema field type).
For example, the following schema allows validating lists of string values whose sizes must not be greater than 5:
class TestSchema < Marten::Schema
field :values, of: :string, max_size: 10
end
As highlighted by the above example, the type of the underlying array member field must be specified through the use of an of
option, which should reference an existing schema field type (such as string
, enum
, etc).
Please refer to the schema field reference to learn more about array
fields.
Image fields for models and schemas
It is now possible to define image
fields in models and schemas, which allow you to store or validate files that are indeed images. This capability requires the use of the crystal-vips shard.
For example:
class ImageAttachment < Marten::Model
field :id, :big_int, primary_key: true, auto: true
field :uploaded_file, :image, blank: false, null: false
end
attachment = ImageAttachment.first!
attachment.uploaded_file # => #<Marten::DB::Field::File::File:0x102dd0ac0 ...>
attachment.uploaded_file.attached? # => true
attachment.uploaded_file.name # => "test.png"
attachment.uploaded_file.size # => 5796929
attachment.uploaded_file.url # => "/media/test.png"
Minor features
Models and databases
- Query sets now support XOR operations when performing complex queries involving
q
expressions. Additionally, combining query sets using the XOR operator (^
) is now also supported (see#^ (XOR)
). - A new
slugify
option was added toslug
model fields in order to make it possible to automatically generate a slug value from another local model field. - Query pages (instances of
Marten::DB::Query::Page
) now expose a#pages_count
method that allows to get the total number of pages. - Related objects are now automatically loaded when accessing backward relations (such as backward many-to-one relations or backward one-to-one relations).
- The ability to retrieve specific records by using raw SQL predicates was introduced. See Fetching single records with raw SQL predicates to learn more about this new capability.
- The
#prefetch
query set method now provides an optionalquery_set
argument, allowing you to specify a custom query set for retrieving prefetched records. - A new
#total_count
method was added to the paginator and page objects to make it possible to retrieve the total number of records in the paginated query set, without applying pagination.
Handlers and HTTP
- Session stores now make it possible to easily configure when session entries expire through the use of the
#expires_at=
,#expires_at_browser_close=
, and#expires_in=
methods. Please refer to Customizing session expiry times to learn more about this capability. - An alias for the
#reverse
handler method (#url
) was introduced. - A Referrer-Policy middleware was introduced to make it possible to automatically set the Referrer-Policy header in responses generated by handlers.
- A new
unsupported_http_method_strategy
setting was introduced to make it possible to configure the strategy to use when processing unsupported HTTP methods in handlers. This setting can be used to configure whether such requests should result in 405 Method Not Allowed responses (the default behavior) or 404 Not Found responses. - It is now possible to use any hash or named tuple to define schema initial data in handlers that use subclasses of
Marten::Handlers::Schema
(in the#initial_data
method). - Incorrect reverse URL resolutions exceptions now incorporate more details related to missing and invalid parameters.
- The ability to define specific exceptions handling callbacks with the
#rescue_from
macro was added to handlers. - The
Marten::Handlers::RecordCreate
generic handler now defines a#save_record
method that can be overridden in order to customize how the new record is saved from the validated schema data. - The
Marten::Handlers::RecordCreate
generic handler now defines a#prepare_record_attributes
method that can be overridden in order to generate a hash of attributes that will be used to create the new record (this hash defaults to the validated schema data). - The
Marten::Handlers::RecordUpdate
generic handler now defines a#save_record
method that can be overridden in order to customize how the record is saved from the validated schema data. - The
Marten::Handlers::RecordUpdate
generic handler now defines a#prepare_record_attributes
method that can be overridden in order to generate a hash of attributes that will be used to update the record (this hash defaults to the validated schema data fields that match the model's fields).
Templates
- A new
localize
template tag was introduced to make it easy to localize values (such as dates, numbers, and time values) within templates. - A new
underscore
template filter was introduced to make it easy to get the underscored version of a string within templates. - An alias for the
url
template tag (reverse
) was introduced.
Schemas
- The
date
anddate_time
schema fields now fall back to the formats specified in thedate_input_formats
anddate_time_input_formats
settings, respectively, when localized formats fail to parse raw field values.
Development
- A new
--log-level
command option was introduced to make it easier to configure the log level to use when running management commands (see Shared options for more details). - The
new
management command now makes it possible to generate projects without configured databases when the--database=none
option is used. - Projects generated with the
new
management command now include the Referrer-Policy middleware by default. - The
new
management command now generates aseed.cr
file when generating new project structures. - A new
seed
management command was introduced to make it easy to execute seed files. - Log entries generated when running the development server (
serve
management command) in debug mode now include more details about processed requests, rendered templates, and executed SQL queries. - Database configuration now supports connection strings, which can be useful in scenarios where only a connection string is provided (e.g., via a
DATABASE_URL
environment variable from cloud providers). See Database settings to learn more about this new capability. - New
date_input_formats
anddate_time_input_formats
settings were introduced to provide additional flexibility in parsingdate
anddate_time
schema field values. These settings allow you to define fallback input formats that are used when localized formats cannot successfully parse rawdate
/date_time
schema field values. - The
new
management command now provides a--with-image-support
option in order to easily generate new projects with support for image fields.
Internationalization
- Translations defined in the
config/locales
folder are now loaded automatically by the framework if defined (see Defining translations to learn more about the places from which translations can be loaded). - A new
i18n.fallbacks
setting was introduced to make it possible to easily configure locale fallbacks.
Backward incompatible changes
Internationalization
- Marten projects now automatically default to using a locale fallback chain that is that set to
["en"]
by default. This means that all the missing translations for a specific locale will be automatically fallbacked to theen
locale by default. This behavior can be customized by updating thei18n.fallbacks
setting.