<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Morgan Aubert</title>
    <description>The latest articles on DEV Community by Morgan Aubert (@ellmetha).</description>
    <link>https://dev.to/ellmetha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F988410%2Fc615b3c3-b715-4c0e-a31f-4dbe08fa0fa7.jpg</url>
      <title>DEV Community: Morgan Aubert</title>
      <link>https://dev.to/ellmetha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ellmetha"/>
    <language>en</language>
    <item>
      <title>Digging into Marten query sets</title>
      <dc:creator>Morgan Aubert</dc:creator>
      <pubDate>Fri, 17 Nov 2023 01:42:27 +0000</pubDate>
      <link>https://dev.to/ellmetha/digging-into-marten-query-sets-3g5l</link>
      <guid>https://dev.to/ellmetha/digging-into-marten-query-sets-3g5l</guid>
      <description>&lt;p&gt;The &lt;a href="https://martenframework.com/"&gt;Marten web framework&lt;/a&gt; incorporates an intuitive object-relational mapper (ORM), streamlining the development process for users who may not possess extensive knowledge of databases and SQL. To facilitate interactions with collections of model records, Marten introduces a dynamic mechanism called "Query sets". A query set represents a collection of model records in the database. It can have filters, be paginated, sliced, etc. In this guide, we will cover how to leverage such querying capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick setup
&lt;/h2&gt;

&lt;p&gt;Before delving into our initial examples of query sets, let's first set up a small project that will serve as the foundation for this guide. Assuming that the Marten CLI is &lt;a href="https://martenframework.com/docs/getting-started/installation"&gt;properly installed&lt;/a&gt;, we can use the &lt;a href="https://martenframework.com/docs/development/reference/management-commands#new"&gt;&lt;code&gt;marten new&lt;/code&gt;&lt;/a&gt; command to do so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;marten new project qset-showcase
&lt;span class="nb"&gt;cd &lt;/span&gt;qset-showcase &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; shards &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's define a very simple &lt;code&gt;User&lt;/code&gt; model by creating a &lt;code&gt;src/models/user.cr&lt;/code&gt; file and copying the following content in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Marten&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:big_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;primary_key: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;auto: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;blank: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;blank: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;with_timestamp_fields&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides us a good opportunity to appreciate Marten's declarative approach to model definition. In Marten, models are articulated as subclasses of the &lt;code&gt;Marten::Model&lt;/code&gt; base class, explicitly outlining their "fields" through the use of a &lt;code&gt;#field&lt;/code&gt; macro.&lt;/p&gt;

&lt;p&gt;Marten’s vision when it comes to models is that everything needed to understand a model should be defined within the model itself. In this light, Marten's models drive tables (and not the reverse way around) and migrations are generated automatically from model definitions. While migrations can still be manually written using a convenient DSL if needed, the core idea revolves around the simplicity of defining a model and its fields to ensure that the framework takes care of the associated table automatically.&lt;/p&gt;

&lt;p&gt;To generate the migration for the &lt;code&gt;User&lt;/code&gt; model that we defined above, we can leverage the &lt;a href="https://martenframework.com/docs/development/reference/management-commands#genmigrations"&gt;&lt;code&gt;marten genmigrations&lt;/code&gt;&lt;/a&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;marten genmigrations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should produce the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generating migrations for app 'main':
  › Creating [src/migrations/202311151921341_create_main_user_table.cr]... DONE
      ○ Create main_user table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we inspect the generated file, we should see the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Generated by Marten 0.3.3 on 2023-11-15 19:21:34 -05:00&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;V202311151921341&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Marten&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;plan&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:main_user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:big_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;primary_key: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;auto: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;254&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:date_time&lt;/span&gt;
      &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="ss"&gt;:updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:date_time&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This migration essentially takes care of creating the database table corresponding to the &lt;code&gt;User&lt;/code&gt; model we defined previously.  Should any adjustments be necessary for this model in the future, the &lt;code&gt;marten genmigrations&lt;/code&gt; command can be executed as many times as needed. When doing so, Marten will generate new migration files for each change and will ensure that the generated migrations are interdependent so that they are applied in the right order.&lt;/p&gt;

&lt;p&gt;We can now apply our automatically-generated migration by running the &lt;a href="https://martenframework.com/docs/development/reference/management-commands#migrate"&gt;&lt;code&gt;marten migrate&lt;/code&gt;&lt;/a&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;marten migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should output something along those lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running migrations:
  › Applying main_202311151921341_create_main_user_table... DONE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;And voilà!&lt;/em&gt; Our database is ready.&lt;/p&gt;

&lt;p&gt;Before delving into query sets, let's finally open a Crystal playbook and let's create a few records. To do so, let's run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crystal play
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now head to &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt; and paste the following Crystal snippet into the live editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"./src/project"&lt;/span&gt;
&lt;span class="no"&gt;Marten&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;

&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="s2"&gt;"john.doe@example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"mary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="s2"&gt;"mary01@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"Mary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;last_name: &lt;/span&gt;&lt;span class="s2"&gt;"Williams"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This essentially requires our Marten project and creates two &lt;code&gt;User&lt;/code&gt; records. We can keep the Crystal playground open as we will be using it for running and testing queries in the following sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are query sets?
&lt;/h2&gt;

&lt;p&gt;A query set represents a specific query specified for a given model. It can involve filters, be paginated, etc. Unless a specific "write" operation is performed on such query sets, they will usually be mapped to a standard &lt;code&gt;SELECT&lt;/code&gt; statement where filters are converted to &lt;code&gt;WHERE&lt;/code&gt; clauses.&lt;/p&gt;

&lt;p&gt;Query sets are &lt;strong&gt;lazily evaluated&lt;/strong&gt;: defining a query set will usually not involve any database operations. Additionally, most methods provided by query sets also return new query set objects. Query sets are only translated to SQL queries hitting the underlying database when records need to be extracted or manipulated by the considered codebase.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;qset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# the query set is not evaluated&lt;/span&gt;
&lt;span class="n"&gt;qset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;last_name: &lt;/span&gt;&lt;span class="s2"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# the query set is not evaluated&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;qset&lt;/span&gt; &lt;span class="c1"&gt;# the query set is evaluated&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic queries
&lt;/h2&gt;

&lt;p&gt;Let's start with some basic query set examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Querying all records
&lt;/h3&gt;

&lt;p&gt;Retrieving all the records of a specific model can be achieved through the use of the &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#all"&gt;&lt;code&gt;#all&lt;/code&gt;&lt;/a&gt; query set method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filtering specific records
&lt;/h3&gt;

&lt;p&gt;Filtering records can be achieved by leveraging the &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#filter"&gt;&lt;code&gt;#filter&lt;/code&gt;&lt;/a&gt; query set method. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will return all &lt;code&gt;User&lt;/code&gt; records whose username is &lt;code&gt;johndoe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is possible to filter records by applying multiple filters. To do so, either multiple arguments can be specified to &lt;code&gt;#filter&lt;/code&gt; or calls to &lt;code&gt;#filter&lt;/code&gt; can be chained. For example, the following queries are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, filters involving multiple parameters like in the above examples always produce SQL queries whose parameters are "AND"ed together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieving single objects
&lt;/h3&gt;

&lt;p&gt;Retrieving a specific record is achieved through the use of the &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#get-1"&gt;&lt;code&gt;#get!&lt;/code&gt;&lt;/a&gt; query set method. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, any kind of filters can be specified to this method, but only one record must be returned. If the record is not found, an exception is raised by this method (&lt;code&gt;Marten::DB::Errors::RecordNotFound&lt;/code&gt;). If multiple records are found, another kind of exception is raised too (&lt;code&gt;Marten::DB::Errors::MultipleRecordsFound&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;It is also possible to use the &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#get"&gt;&lt;code&gt;#get&lt;/code&gt;&lt;/a&gt; method, which will simply return &lt;code&gt;nil&lt;/code&gt; if the record is not found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieving the first or last record
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#first"&gt;&lt;code&gt;#first&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#last"&gt;&lt;code&gt;#last&lt;/code&gt;&lt;/a&gt; query set methods can be used to retrieve the first or last record for a given query set. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;

&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ordering records
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#order"&gt;&lt;code&gt;#order&lt;/code&gt;&lt;/a&gt; query set method can be used to specify in which order records should be queried. Multiple fields can be specified in order to define the final ordering.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;qset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
&lt;span class="n"&gt;qset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, records would be ordered by descending creation date (because of the &lt;code&gt;-&lt;/code&gt; prefix), and then by username (ascending).&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced queries
&lt;/h2&gt;

&lt;p&gt;Now that we covered some of the fundamental query set operations, let's delve into more advanced examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filter predicates
&lt;/h3&gt;

&lt;p&gt;Filter predicates define the type of filtering that is done at the SQL level. They map to &lt;code&gt;WHERE&lt;/code&gt; clauses in the produced SQL queries.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username__icontains: &lt;/span&gt;&lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will translate to a SQL query like the following one (using PostgreSQL's syntax):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;main_user&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="k"&gt;LIKE&lt;/span&gt; &lt;span class="k"&gt;UPPER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"john"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, unless explicitly specified, the exact predicate (exact match) is used for all filters. As such, the following two query sets are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username__exact: &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the double underscores notation used in the above examples: &lt;code&gt;__&lt;/code&gt; is used to separate the filtered field name (here, &lt;code&gt;username&lt;/code&gt;) from the type of filtering that is intended to be performed on the corresponding column.&lt;/p&gt;

&lt;p&gt;Other predicates can be used, such as &lt;code&gt;iexact&lt;/code&gt; (case-insensitive match), &lt;code&gt;contains&lt;/code&gt; (containment test), &lt;code&gt;startswith&lt;/code&gt; (starts-with test), etc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username__startswith: &lt;/span&gt;&lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username__contains: &lt;/span&gt;&lt;span class="s2"&gt;"do"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Complex filters with &lt;code&gt;q&lt;/code&gt; expressions
&lt;/h3&gt;

&lt;p&gt;As mentioned previously, field predicates expressed as keyword arguments to the &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#filter"&gt;&lt;code&gt;#filter&lt;/code&gt;&lt;/a&gt; method will use an &lt;code&gt;AND&lt;/code&gt; operator in the produced &lt;code&gt;WHERE&lt;/code&gt; clauses. In order to produce conditions using other operators, it is necessary to use "&lt;code&gt;q&lt;/code&gt; expressions".&lt;/p&gt;

&lt;p&gt;In this light, most of the methods we mentioned previously like &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#filter"&gt;&lt;code&gt;#filter&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#get"&gt;&lt;code&gt;#get&lt;/code&gt;&lt;/a&gt; can receive a block allowing to define complex conditions. Inside of this block, a &lt;code&gt;#q&lt;/code&gt; method can be used in order to define conditions nodes that can be combined together using the following logical operators: &lt;code&gt;&amp;amp;&lt;/code&gt; (logical "AND"), &lt;code&gt;|&lt;/code&gt; (logical "OR"), and &lt;code&gt;-&lt;/code&gt; (logical negation).&lt;/p&gt;

&lt;p&gt;For example, the following snippet will return all the &lt;code&gt;User&lt;/code&gt; records whose username starts with "john" or "mary":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username__startswith: &lt;/span&gt;&lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username__startswith: &lt;/span&gt;&lt;span class="s2"&gt;"mary"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this approach, it is possible to produce complex conditions by combining &lt;code&gt;q&lt;/code&gt; expressions with the &lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, and &lt;code&gt;-&lt;/code&gt; operators. Parentheses can also be used to group statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"Mary"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; 
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;last_name: &lt;/span&gt;&lt;span class="s2"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Paginating results
&lt;/h3&gt;

&lt;p&gt;Marten query sets provide a built-in pagination mechanism that you can leverage in order to easily iterate over records that are split across several pages of data. In this light, each query set has the capability to generate "paginator" objects that are initialized with a given page size and that can be used to request specific pages.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;query_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;

&lt;span class="n"&gt;paginator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query_set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paginator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;paginator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;page_size&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; 10&lt;/span&gt;
&lt;span class="n"&gt;paginator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pages_count&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 6&lt;/span&gt;

&lt;span class="c1"&gt;# Retrieve the first page and iterate over the underlying records&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paginator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;               &lt;span class="c1"&gt;# 1&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous_page?&lt;/span&gt;       &lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;previous_page_number&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next_page?&lt;/span&gt;           &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next_page_number&lt;/span&gt;     &lt;span class="c1"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, each page object also gives access to some useful metadata (sibling page numbers, etc) in order to build pagination features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performing raw SQL queries
&lt;/h3&gt;

&lt;p&gt;Marten also lets you get fully instantiated records retrieved from &lt;a href="https://martenframework.com/docs/models-and-databases/raw-sql"&gt;raw SQL queries&lt;/a&gt;. This can be achieved by leveraging the &lt;a href="https://martenframework.com/docs/models-and-databases/reference/query-set#raw"&gt;&lt;code&gt;#raw&lt;/code&gt;&lt;/a&gt; query set method.&lt;/p&gt;

&lt;p&gt;For example, the following snippet would allow iterating over all the &lt;code&gt;User&lt;/code&gt; model records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"select * from main_user"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# Do something with `user` record&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is worth mentioning that is is possible to "inject" parameters into raw SQL queries. Both positional and named arguments are supported. Positional parameters must be specified using the &lt;code&gt;?&lt;/code&gt; syntax while named parameters must be specified using the &lt;code&gt;:param&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using positional arguments:&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;"SELECT * FROM main_user WHERE first_name = ? and created_at &amp;gt; ?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="s2"&gt;"2023-11-16"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Using named arguments:&lt;/span&gt;
&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;"SELECT * FROM main_user WHERE first_name = :first_name and created_at &amp;gt; :created_at"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="ss"&gt;created_at: &lt;/span&gt;&lt;span class="s2"&gt;"2023-11-16"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we delved into Marten's user-friendly object-relational mapper (ORM) and its dynamic "Query sets" mechanism, designed to simplify database interactions in web application projects. We covered both fundamental and advanced query operations, demonstrating Marten's adaptability for building efficient, database-driven applications. It's important to note that our coverage only scratched the surface of Marten's capabilities, as we did not explore more complex scenarios involving &lt;a href="https://martenframework.com/docs/models-and-databases/introduction#relationships"&gt;relationships&lt;/a&gt;, &lt;a href="https://martenframework.com/docs/models-and-databases/queries#joins-and-filtering-relations"&gt;joins&lt;/a&gt;, and other advanced query set functionalities.&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>orm</category>
      <category>database</category>
      <category>marten</category>
    </item>
    <item>
      <title>Background job processing with Marten and Mosquito</title>
      <dc:creator>Morgan Aubert</dc:creator>
      <pubDate>Sat, 08 Apr 2023 21:19:33 +0000</pubDate>
      <link>https://dev.to/ellmetha/background-job-processing-with-marten-and-mosquito-2i3o</link>
      <guid>https://dev.to/ellmetha/background-job-processing-with-marten-and-mosquito-2i3o</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/martenframework/marten"&gt;Marten&lt;/a&gt; is a web framework written in Crystal that makes building web applications easy and enjoyable. &lt;a href="https://github.com/mosquito-cr/mosquito"&gt;Mosquito&lt;/a&gt; is a background task runner for Crystal that uses Redis and that makes it easy to schedule and run tasks asynchronously.&lt;/p&gt;

&lt;p&gt;Combining Marten with Mosquito can be a powerful way to build web applications with background tasks that run asynchronously. In this blog post, we'll show you how to get started with using Marten and Mosquito together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Assuming that you already have a working Marten project that was initialized with the &lt;a href="https://martenframework.com/docs/authentication/introduction"&gt;built-in authentication&lt;/a&gt; at hand, you can start by adding Mosquito to your &lt;code&gt;shard.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mosquito&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mosquito-cr/mosquito&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;shards install&lt;/code&gt; to install the new dependencies.&lt;/p&gt;

&lt;p&gt;We can now ensure that Mosquito is properly required by our project. To do so, let's update the content of the &lt;code&gt;src/project.cr&lt;/code&gt; file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Third party requirements.&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"marten"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"mosquito"&lt;/span&gt;
&lt;span class="c1"&gt;# other requirements...&lt;/span&gt;

&lt;span class="c1"&gt;# Project requirements.&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"./jobs/**"&lt;/span&gt;

&lt;span class="c1"&gt;# other requirements...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice that we require both &lt;code&gt;mosquito&lt;/code&gt; and the files of a &lt;code&gt;jobs&lt;/code&gt; folder, where we'll define the actual jobs.&lt;/p&gt;

&lt;p&gt;Now we can create a new &lt;code&gt;config/initializers/mosquito.cr&lt;/code&gt; initializer file where the actual Mosquito configuration will live. We won't cover all the &lt;a href="https://mosquito-cr.github.io/manual/index.html#configuration"&gt;Mosquito configuration options&lt;/a&gt; in this article, but this initializer could simply set the right Redis URL to use for now and could look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="no"&gt;Mosquito&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"REDIS_URL"&lt;/span&gt;&lt;span class="p"&gt;]?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;"redis://localhost:6379"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to create a new file where we will (i) setup Marten itself and (ii) start the Mosquito runner. In this light, let's create a new &lt;code&gt;src/worker.cr&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"./project"&lt;/span&gt;

&lt;span class="no"&gt;Marten&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;

&lt;span class="no"&gt;Mosquito&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining jobs
&lt;/h2&gt;

&lt;p&gt;For the purpose of this article, we will be defining jobs under a &lt;code&gt;src/jobs&lt;/code&gt; folder. If your Marten project is split into  multiple &lt;a href="https://martenframework.com/docs/development/applications"&gt;applications&lt;/a&gt;, you can also decide to create a &lt;code&gt;jobs&lt;/code&gt; folder inside each of these applications.&lt;/p&gt;

&lt;p&gt;So let's create a &lt;code&gt;src/jobs&lt;/code&gt; folder for now and let's define a &lt;code&gt;send_welcome_email_job.cr&lt;/code&gt; file in it with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendWelcomeEmailJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Mosquito&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;QueuedJob&lt;/span&gt;
  &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_welcome_email&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;welcome_email_sent: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example job simply retrieves a &lt;code&gt;User&lt;/code&gt; model record using a &lt;code&gt;user_id&lt;/code&gt; job parameter, sends an email by calling a hypothetical &lt;code&gt;#send_welcome_email&lt;/code&gt; method, and updates the considered record by setting a hypothetical  &lt;code&gt;welcome_email_sent&lt;/code&gt; field to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enqueuing jobs
&lt;/h2&gt;

&lt;p&gt;Enqueuing a job is as simple as initializing an instance of a job class with the specified parameters and calling the &lt;code&gt;#enqueue&lt;/code&gt; method. The job above was all about sending a welcome email to newly created users. As such, this job could be enqueued from a &lt;a href="https://martenframework.com/docs/models-and-databases/callbacks"&gt;callback&lt;/a&gt; that we could define in the &lt;code&gt;Auth::User&lt;/code&gt; model. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Auth&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MartenAuth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;
    &lt;span class="n"&gt;after_commit&lt;/span&gt; &lt;span class="ss"&gt;:trigger_welcome_email_sending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :create&lt;/span&gt;

    &lt;span class="kp"&gt;private&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trigger_welcome_email_sending&lt;/span&gt;
      &lt;span class="no"&gt;SendWelcomeEmailJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i64&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;enqueue&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we are triggering the job from a model callback but it should be noted that you can enqueue jobs from pretty much anywhere in your Marten project codebase (eg. &lt;a href="https://martenframework.com/docs/handlers-and-http/introduction"&gt;handlers&lt;/a&gt;, &lt;a href="https://martenframework.com/docs/schemas/introduction"&gt;schemas&lt;/a&gt;, etc).&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Mosquito worker
&lt;/h2&gt;

&lt;p&gt;As you might have guessed, the Mosquito worker runs in a dedicated process. This means that we have to explicitly start the runner we defined earlier by compiling and executing the &lt;code&gt;src/worker.cr&lt;/code&gt; file. While in development, we can simply leverage the &lt;code&gt;crystal run&lt;/code&gt; command to do so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crystal run src/worker.cr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A few tips regarding deployments
&lt;/h2&gt;

&lt;p&gt;At deployment time, it's likely that you already compile two binaries: your project's server (&lt;code&gt;src/server.cr&lt;/code&gt;) and your project's management CLI (&lt;code&gt;manage.cr&lt;/code&gt;). In addition to these, you will now need to ensure that your worker is compiled as well. This can be accomplished by relying on the &lt;code&gt;crystal build&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crystal build src/worker.cr &lt;span class="nt"&gt;-o&lt;/span&gt; bin/worker &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could also add a target to your &lt;code&gt;shard.yml&lt;/code&gt; file and even trigger the execution of your compiled worker from a &lt;code&gt;Procfile&lt;/code&gt; file depending on your deployment strategy. You can learn more about deploying Marten in the &lt;a href="https://martenframework.com/docs/deployment/introduction"&gt;dedicated documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog post, we've gone through the steps of setting up Mosquito with Marten, including installation, configuration, and usage. Using Mosquito with the Marten web framework can help you build fast and scalable web applications that leverage background job processing capabilities.&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>marten</category>
    </item>
    <item>
      <title>The vision behind the Marten web framework</title>
      <dc:creator>Morgan Aubert</dc:creator>
      <pubDate>Mon, 12 Dec 2022 02:11:29 +0000</pubDate>
      <link>https://dev.to/ellmetha/the-vision-behind-the-marten-web-framework-1e09</link>
      <guid>https://dev.to/ellmetha/the-vision-behind-the-marten-web-framework-1e09</guid>
      <description>&lt;p&gt;Over the course of my career, I used to work extensively with two web frameworks: &lt;a href="https://www.djangoproject.com"&gt;Django&lt;/a&gt; and &lt;a href="https://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt;. These two frameworks are regularly compared, and I can't even imagine the number of articles or discussions that touched on this subject over the years. The bottom line is that both frameworks have their strengths: in my opinion, Django shines with its design decisions and the general assumptions it makes about things like models, migrations, templates, routing, etc. Rails shines with its awesome DSLs (like callbacks, or validations) and the overall productivity it enables.  &lt;/p&gt;

&lt;p&gt;A few years ago, I was trying &lt;a href="https://dev.to/scottw/sorbet-5fdf-temp-slug-1554971"&gt;Sorbet&lt;/a&gt; for the first time and I was realizing how frustrating the developer experience provided by this tool was: horrible syntax with &lt;a href="https://sorbet.org/docs/sigs#sig-annotating-method-signatures"&gt;sig&lt;/a&gt; extensions (and duplicated method definitions), magic comments, separate RBI files generated from the codebase, ... Don't get me wrong: Sorbet certainly fulfills its mission of bringing typing to the Ruby ecosystem, and enabling most of the benefits that come with typed languages. But unfortunately, this is to the detriment of the developer experience because all of this makes Ruby lose its beauty and slickness.  &lt;/p&gt;

&lt;p&gt;Developer experience matters. And well, while I was reading more on Sorbet, I stumbled upon a language called &lt;a href="https://crystal-lang.org/"&gt;Crystal&lt;/a&gt;. The timing couldn't have been better: Crystal - heavily inspired by Ruby's syntax - provided exactly the kind of typing syntax that I would've loved to rely on in a "typed" Ruby: elegant, intuitive, and expressive.  &lt;/p&gt;

&lt;p&gt;On top of that, Crystal featured a bunch of other very interesting characteristics:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A powerful compilation&lt;/strong&gt; and the ability to catch typing errors at compile time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meta-programming&lt;/strong&gt; capabilities with macros&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Very good performances&lt;/strong&gt; (in a lot of benchmarks, Crystal regularly beats other compiled languages like Go or Elixir)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I literally fell in love with the language and started playing with it regularly. Soon I started playing with the existing options in terms of high-level web frameworks (mainly &lt;a href="https://amberframework.org/"&gt;Amber&lt;/a&gt; and &lt;a href="https://luckyframework.org/"&gt;Lucky&lt;/a&gt;). I thought it would be fun to create a web framework that enabled design decisions similar to Django's while also leveraging Crystal's syntax and performances to enable an enjoyable and productive developer experience. That's how I started working on the &lt;a href="https://martenframework.com/"&gt;Marten web framework&lt;/a&gt;.  &lt;/p&gt;

&lt;h1&gt;
  
  
  What is Marten?
&lt;/h1&gt;

&lt;p&gt;Marten is a Crystal Web framework that enables pragmatic development and rapid prototyping. It provides a consistent and extensible set of tools that developers can leverage to build web applications without reinventing the wheel.&lt;/p&gt;

&lt;h1&gt;
  
  
  Principles
&lt;/h1&gt;

&lt;p&gt;Marten's development has been guided by a few key principles. As it stands, Marten focuses on the following aspects:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple and easy to use:&lt;/strong&gt; Marten tries to ensure that everything it enables is as simple as possible and that the syntax provided for dealing with the framework's components remains obvious and easy to remember (and certainly not complex or obscure). The framework makes it as easy as possible to leverage its capabilities and perform CRUD operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-featured&lt;/strong&gt; : Marten adheres to the "batteries included" philosophy. Out of the box, it provides the tools and features that are commonly required by web applications: ORM, migrations, translations, templating engine, sessions, and (soon) emailing and authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible:&lt;/strong&gt; Marten gives developers the ability to contribute extra functionalities to the framework easily. Things like custom model field implementations, new route parameter types, session stores, etc... can all be registered to the framework easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DB-Neutral:&lt;/strong&gt; The framework's ORM is usable with multiple database backends (including MySQL, PostgreSQL, and SQLite).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App-oriented:&lt;/strong&gt; Marten allows separating projects into a set of logical "apps", which helps improve code organization and makes it easy for multiple developers to work on different components. Each app can contribute specific abstractions and features to a project like models and migrations, templates, HTTP handlers and routes, etc. These apps can also be extracted in &lt;a href="https://crystal-lang.org/reference/guides/writing_shards.html#whats-a-shard"&gt;Crystal shards&lt;/a&gt; in order to contribute features and behaviours to other Marten projects. The goal behind this capability is to allow the creation of a powerful apps ecosystem over time and to encourage "reusability" and "pluggability" &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend-oriented:&lt;/strong&gt; The framework is intentionally very "backend-oriented" because the idea is to not make too many assumptions regarding how the frontend code and assets should be structured, packaged or bundled together. The framework can't account for all the ways assets can be packaged and/or bundled together and does not advocate for specific solutions in this area. Some projects might require a webpack strategy to bundle assets, some might require a fingerprinting step on top of that, and others might need something entirely different. How these toolchains are configured or set up is left to the discretion of web application developers, and the framework simply makes it easy to reference these assets and collect them at deploy time to upload them to their final destination&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What does it look like?
&lt;/h1&gt;

&lt;p&gt;As mentioned previously, Marten provides support for many key components in order to help developers build web applications in a productive way. The most important ones certainly are &lt;strong&gt;models&lt;/strong&gt; , &lt;strong&gt;templates&lt;/strong&gt; , and &lt;strong&gt;handlers&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://martenframework.com/docs/models-and-databases"&gt;&lt;strong&gt;Models&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;let you define what data can be persisted in your application:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Marten&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:big_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;primary_key: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;auto: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;max_size: &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:text&lt;/span&gt;
  &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:many_to_one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Marten’s vision when it comes to models is that everything needed to understand a model should be defined within the model itself. In this light, Marten’s models drive tables (and not the reverse way around) and &lt;a href="https://martenframework.com/docs/models-and-databases/migrations"&gt;migrations are generated automatically&lt;/a&gt; from model definitions. Migrations can still be written manually using a convenient DSL if necessary, but the idea is that defining a model and its fields is all that is necessary in order to have a corresponding table taken care of automatically by the framework. This is a very convenient mechanism: most Crystal web frameworks require that you write the migrations corresponding to your model definitions manually; being able to rely on an automatic mechanism that does this for you by default is certainly a plus.  &lt;/p&gt;

&lt;p&gt;As highlighted in the above snippet, models explicitly define "fields" and relationships through the use of a unique and simple field macro. These fields can contribute database columns to the model table and they can be queried through the use of an &lt;a href="https://martenframework.com/docs/models-and-databases/queries"&gt;automatically-generated database access API&lt;/a&gt;. One interesting aspect of model fields is that they operate at a higher level than columns: they can actually contribute  features or validations to your models and they don't have to correspond to primitive types only. For example, an email model field could ensure that only email address values are allowed for a specific field while also contributing a string column at the database level.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://martenframework.com/docs/templates"&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;let you define your presentation logic:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{% extend "base.html" %}
{% block content %}
&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  {% for article in articles %}
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;{{ article.title }}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  {% endfor %}
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
{% endblock content %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Templates provide a convenient way of defining your presentation logic and writing contents (such as HTML) that are rendered dynamically. These renderings can involve model records or any other variables needed for the templates' requirements.  &lt;/p&gt;

&lt;p&gt;Marten's templates provide a Jinja-like syntax where you can use &lt;a href="https://martenframework.com/docs/templates/introduction#variables"&gt;dynamic variables&lt;/a&gt; as well as some programming constructs and leverage relatively common patterns such as &lt;a href="https://martenframework.com/docs/templates/introduction#tags"&gt;template tags&lt;/a&gt; or &lt;a href="https://martenframework.com/docs/templates/introduction#filters"&gt;filters&lt;/a&gt;. This syntax is relatively common now and has been used in a lot of projects such as Django, Liquid, or Nunjucks. The advantage of relying on a dedicated templating engine is that templates don't assume Crystal knowledge. As such, the framework acknowledges the fact that such templates may be written by developers of various backgrounds that don't necessarily work on the backend of the project.  &lt;/p&gt;

&lt;p&gt;Moreover, these templates are parsed and rendered at runtime. As such, they are not tied to the compilation process of the project's Crystal binary. This makes them convenient to edit (because they don't require a compilation), which is a plus for projects involving lots of templates. Obviously, the use of these templates (although recommended by the framework) is optional and &lt;a href="https://crystal-lang.org/api/ECR.html"&gt;ECR&lt;/a&gt; (Crystal's compiled template language) can technically be used instead.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://martenframework.com/docs/handlers-and-http"&gt;&lt;strong&gt;Handlers&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;let you process HTTP requests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleListHandler&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Marten&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Handler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s2"&gt;"articles/list.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;articles: &lt;/span&gt;&lt;span class="no"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handlers are responsible for processing HTTP requests and for returning HTTP responses. They are the equivalent of a function that would take a request in and that would produce a response out. In the process they can do possibly anything: loading records from the database, rendering HTML templates, producing JSON payloads, ...  &lt;/p&gt;

&lt;p&gt;Routing in Marten only cares about URL paths. As such the framework does not route based on HTTP methods and it is the responsibility of the mapped handlers to implement the right logic based on the incoming request's verb. For example, a handler might display an HTML page containing a form when processing a GET request, and it might validate possible form data when handling a POST request.  &lt;/p&gt;

&lt;p&gt;Marten recognizes the existence of common or frequently encountered handler patterns, like the form example I just mentioned above. As such, the framework includes a set of &lt;a href="https://martenframework.com/docs/handlers-and-http/generic-handlers"&gt;generic handlers&lt;/a&gt; that can be leveraged to perform common tasks. These tasks are frequently encountered when working on web applications. For example: displaying a list of records extracted from the database, or deleting a record. Generic handlers take care of these common patterns so that developers - again - don't end up reimplementing the wheel.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Obviously, this only scratches the surface of what's possible with the Marten web framework. You can have a look at the documentation in order to learn more about other components or features such as&lt;/em&gt; &lt;a href="https://martenframework.com/docs/handlers-and-http/routing"&gt;&lt;em&gt;routing&lt;/em&gt;&lt;/a&gt; &lt;em&gt;(allowing to map your handlers to URL paths),&lt;/em&gt; &lt;a href="https://martenframework.com/docs/schemas"&gt;&lt;em&gt;schemas&lt;/em&gt;&lt;/a&gt; &lt;em&gt;(allowing to validate request data),&lt;/em&gt; &lt;a href="https://martenframework.com/docs/files"&gt;&lt;em&gt;file management&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://martenframework.com/docs/i18n"&gt;&lt;em&gt;internationalization&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://martenframework.com/docs/development/management-commands"&gt;&lt;em&gt;management commands&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://martenframework.com/docs/security"&gt;&lt;em&gt;security helpers&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href="https://martenframework.com/docs/files/asset-handling"&gt;&lt;em&gt;assets management&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,...&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Get started with Marten
&lt;/h1&gt;

&lt;p&gt;Here are a few ideas on how you can get started with Marten:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/martenframework/marten"&gt;Marten GitHub repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href="https://martenframework.com/docs/"&gt;official documentation&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://martenframework.com/docs/getting-started/installation"&gt;installation guide&lt;/a&gt; will help you install Crystal and the Marten CLI&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://martenframework.com/docs/getting-started/tutorial"&gt;introduction tutorial&lt;/a&gt; will help you discover the main features of the framework by creating a simple web application&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Ask for help or chat with the community in our &lt;a href="https://martenframework.com/chat"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>crystal</category>
      <category>marten</category>
    </item>
  </channel>
</rss>
