<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cache Crew</title>
	<atom:link href="http://cachecrew.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://cachecrew.com/</link>
	<description>Adventures of One Startup Crew</description>
	<lastBuildDate>Fri, 05 Sep 2025 01:42:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
<site xmlns="com-wordpress:feed-additions:1">103835086</site>	<item>
		<title>Data layer: Model, Entity, DTO, and DAO</title>
		<link>https://cachecrew.com/data-layer-model-entity-dto-and-dao/</link>
					<comments>https://cachecrew.com/data-layer-model-entity-dto-and-dao/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Thu, 04 Sep 2025 21:06:18 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=4744</guid>

					<description><![CDATA[There&#8217;s confusion and ambiguity in data layer terminology, especially if you are not in the habit of defining data layers of an application from the ground up.  Let&#8217;s try to clear this up. Why is this important? Terminology is important to ensure a common understanding and communication of concepts so that the team is on [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>There&#8217;s confusion and ambiguity in data layer terminology, especially if you are not in the habit of defining data layers of an application from the ground up.  Let&#8217;s try to clear this up. Why is this important? Terminology is important to ensure a common understanding and communication of concepts so that the team is on the same track as it evolves and interacts with the data. Getting data wrong leads to bugs and inefficiencies in the application. Maintaining a clear abstract definition of data definition and organization helps to mitigate such problems.</p>
<p>There is often a disparity between the concrete representation and storage of data from its necessary use within the application. Let&#8217;s break down each concept by how they work together to create a data layer segregated into sub-layers with specific responsibilities.</p>
<figure class="wp-block-table is-style-stripes has-small-font-size">
<table>
<thead>
<tr>
<th>Concept</th>
<th>Layer</th>
<th>Primary Purpose</th>
<th>Key Trait</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Entity</strong></td>
<td>Persistence</td>
<td>Mirror DB structure</td>
<td>Contains ORM mappings (e.g., @<code>Entity</code>)</td>
</tr>
<tr>
<td><strong>Model</strong></td>
<td>Domain/Business</td>
<td>Enforce business rules and logic</td>
<td>The core “truth” of your application</td>
</tr>
<tr>
<td><strong>DTO</strong></td>
<td>Service/Presentation</td>
<td>Transfer data across process boundaries</td>
<td>A simple data bag with no logic</td>
</tr>
<tr>
<td><strong>DAO</strong></td>
<td>Persistence</td>
<td>Abstract DB access operations</td>
<td>Provides CRUD methods for an Entity</td>
</tr>
</tbody>
</table>
</figure>
<p>So, to get terminology correct, we will explain the difference between an “entity” and “model” and how DTO and DAO play roles. The core difference is one of <strong>concern and context</strong>: an <strong>Entity</strong> is about the <strong>database representation</strong>, while a <strong>Model</strong> is about the <strong>business logic representation</strong>.</p>
<h2>Entity: The Database Ambassador</h2>
<p class="ds-markdown-paragraph">An <strong>Entity</strong> is a class that is <strong>directly mapped to a database table</strong>. Its purpose is to represent the state and structure of a database record.</p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>Primary Concern:</strong> Data Persistence</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Lives in:</strong> The Data Access/Persistence Layer</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Characteristics:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">Each instance corresponds to a row in a table.</p>
</li>
<li>
<p class="ds-markdown-paragraph">Its fields/properties map directly to table columns.</p>
</li>
<li>
<p class="ds-markdown-paragraph">It often includes ORM (Object-Relational Mapping) annotations like <code>@Entity</code>, <code>@Table</code>, <code>@Column</code> (in Java/JPA) or similar decorators in other languages (e.g., <code>[Table]</code> in C#, <code>@entity</code> in Python with SQLAlchemy).</p>
</li>
<li>
<p class="ds-markdown-paragraph">It defines relationships (e.g., <code>@OneToMany</code>, <code>@ManyToOne</code>) to other entities.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Example:</strong> A <code>UserEntity</code> class with an <code>id</code>, <code>username</code>, <code>password_hash</code>, <code>created_date</code>, etc., that exactly matches the <code>users</code> database table.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="java">// Java (JPA) Example
@Entity
@Table(name = "users")
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", nullable = false, unique = true)
    private String username;

    @Column(name = "password_hash", nullable = false)
    private String passwordHash;

    // ORM Annotations, getters, and setters
}</pre>
</li>
</ul>
<h2>Model (aka Domain Model): The Business Brain</h2>
<p class="ds-markdown-paragraph">A <strong>Model</strong> (also often called a <strong>Domain Model</strong> or <strong>Business Model</strong>) is a class that represents a core concept of your business domain. It contains both data and the behavior (business logic) that operates on that data.</p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>Primary Concern:</strong> Implementing Business Logic and Rules.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Lives in:</strong> The Domain Layer (the heart of the application).  It is <strong>persistence-ignorant</strong> (no ORM annotations) and rich with business methods.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Characteristics:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">It is <strong>persistence-ignorant</strong>; it has no knowledge of how or where its data is saved. It should not have any ORM annotations.</p>
</li>
<li>
<p class="ds-markdown-paragraph">Encapsulates the business rules and logic of your application — methods that enforce business rules (e.g., <code>calculateTotal()</code>, <code>validate()</code>, <code>changePassword()</code>).</p>
</li>
<li>
<p class="ds-markdown-paragraph">It is the most important layer and should be the least likely to change if your database or API changes.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Example:</strong> A <code>User</code> model that has a method <code>changePassword()</code> which enforces password complexity rules before updating its own <code>password</code> field.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="java">// Java Example - Pure Domain Model
public class User {
    private Long id;
    private String username;
    private String password; // Might be hashed by a service, not the model itself

    // Business logic lives here
    public boolean isValidPassword(String inputPassword) {
        // Logic to validate password against stored hash
        return PasswordEncoder.matches(inputPassword, this.password);
    }

    // Getters and setters might have validation logic
    public void setUsername(String username) {
        if (username == null || username.trim().isEmpty()) {
            throw new IllegalArgumentException("Username cannot be empty");
        }
        this.username = username;
    }
    // ... other getters and setters
}</pre>
</li>
</ul>
<p>The <code>Model</code> is the &#8220;truth&#8221; of your business. The <code>Entity</code> is just a persistence mechanism for that model. In simpler applications, the Entity and the Model are often the same class, but this is considered an anti-pattern in complex domains because it couples your business logic to your database schema.</p>
<h2>Data Transfer Object (DTO): The Data Courier</h2>
<p class="ds-markdown-paragraph">A <strong>DTO</strong> is a simple container for data used to move information between layers, especially across network boundaries. Its sole purpose is to reduce the number of method calls by aggregating data.</p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>Primary Concern:</strong> Data Transfer, often over a network (e.g., API requests/responses).</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Lives in:</strong> The Service Layer or Presentation Layer.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Characteristics:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">It contains <strong>no business logic</strong>—only fields, getters, and setters.</p>
</li>
<li>
<p class="ds-markdown-paragraph">It is often tailored to a specific use case (e.g., <code>UserCreationRequest</code>, <code>UserSummaryResponse</code>).</p>
</li>
<li>
<p class="ds-markdown-paragraph">Provides a stable, decoupled contract for external communication; used to decouple your internal domain/entity from your external API contract.</p>
</li>
<li>
<p class="ds-markdown-paragraph">It protects your API from internal changes. You can change your <code>User</code> model&#8217;s structure without breaking your API clients, and vice-versa.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Example:</strong> A <code>UserDto</code> sent to a web client that excludes sensitive fields like <code>passwordHash</code> and includes a calculated <code>fullName</code> field.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="java">// Example DTO for sending user data to a client
public class UserDto {
    private Long id;
    private String username;
    private String email;
    private String fullName; // A field that might not exist in the Entity

    // No logic, only getters and setters
    public String getFullName() {
        return fullName;
    }
    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
}</pre>
</li>
</ul>
<h2>Data Access Object (DAO)</h2>
<p class="ds-markdown-paragraph">A <strong>DAO</strong> is a design pattern that provides an abstract interface to the database. It hides all the intricate details of the persistence mechanism (e.g., SQL, NoSQL queries) from the rest of the application.</p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>Primary Concern:</strong> Abstracting data access and persistence operations.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Lives in:</strong> The Data Access Layer.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Characteristics:</strong></p>
<ul>
<li>Separates persistence logic from business logic.</li>
<li>
<p class="ds-markdown-paragraph">It provides <strong>CRUD</strong> (Create, Read, Update, Delete) operations for a specific entity/model.</p>
</li>
<li>
<p class="ds-markdown-paragraph">The application uses the DAO interface, not direct database calls. This makes it easy to switch databases (e.g., from MySQL to PostgreSQL) or switch from SQL to a web API.</p>
</li>
<li>
<p class="ds-markdown-paragraph">In modern development, the <strong>DAO is often replaced or implemented by an ORM</strong> (like Hibernate, Entity Framework, Django ORM, Sequelize). The Repository pattern is a more advanced evolution of the DAO pattern.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Example:</strong> A <code>UserDao</code> interface with methods like <code>findById</code>, <code>save</code>, <code>delete</code>, and <code>findAll</code>.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">// DAO Interface
public interface UserDao {
    Optional&lt;UserEntity&gt; findById(Long id);
    List&lt;UserEntity&gt; findAll();
    UserEntity save(UserEntity user);
    void delete(Long id);
}

// JPA-based implementation of the DAO interface
@Repository // Spring stereotype marking this as a DAO
public class JpaUserDao implements UserDao {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Optional&lt;UserEntity&gt; findById(Long id) {
        return Optional.ofNullable(entityManager.find(UserEntity.class, id));
    }
    // ... implement other methods
}</pre>
</li>
</ul>
<h1>How They Work Together in a Flow</h1>
<p class="ds-markdown-paragraph">Let&#8217;s imagine an API endpoint <code>GET /users/{id}</code>:</p>
<ol start="1">
<li>
<p class="ds-markdown-paragraph"><strong>Presentation Layer (Controller):</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">Receives the HTTP request and extracts the user <code>id</code>.</p>
</li>
<li>
<p class="ds-markdown-paragraph">Calls a method on a <strong>Service</strong>.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Service Layer:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">The service contains business logic. It calls a <strong>DAO</strong> to fetch the data.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Data Access Layer (DAO):</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">The <strong>DAO</strong> (e.g., <code>userDao.findById(id)</code>) executes the database query.</p>
</li>
<li>
<p class="ds-markdown-paragraph">It returns a <strong>UserEntity</strong> object, which is a direct representation of the database row.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Service Layer (cont.):</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">The service might perform operations using the <strong>User</strong> model (if one exists). It might convert the <code>UserEntity</code> to a <code>User</code> domain model to apply business rules.</p>
</li>
<li>
<p class="ds-markdown-paragraph">It then converts the result (either the <code>UserEntity</code> or the <code>User</code> model) into a <strong>UserDTO</strong> tailored for the response (e.g., hiding the password hash, formatting names).</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Presentation Layer (Controller):</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">The controller receives the <strong>UserDTO</strong> from the service and serializes it to JSON to send back in the HTTP response.</p>
</li>
</ul>
</li>
</ol>
<p class="ds-markdown-paragraph">This flow ensures each layer has a single responsibility and is decoupled from the others, leading to maintainable, testable, and flexible software.</p>
<h2>DTOs and Models: A Flexible Relationship</h2>
<p class="ds-markdown-paragraph"><em>DTOs closely parallel (and may even match) the corresponding data model</em></p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>Often True, but Not a Rule:</strong> It&#8217;s very common for a DTO to initially look identical to the domain model it represents, especially for simple CRUD operations. A <code>UserModel</code> might have <code>id</code>, <code>name</code>, <code>email</code>, and the <code>UserResponseDto</code> might have those same fields.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>The Divergence is the Point:</strong> The power of the DTO pattern emerges when they <strong>stop</strong> matching. DTOs are tailored to the specific needs of a client or use case, while the Model is the single source of truth.</p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>Combination:</strong> A <code>UserProfileDto</code> might combine data from a <code>UserModel</code> and a <code>UserProfileModel</code>.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Omission:</strong> A <code>PublicUserDto</code> might return a user&#8217;s <code>name</code> and <code>avatarUrl</code> but omit their <code>email</code> for privacy.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Addition:</strong> A <code>UserDto</code> might include a calculated field like <code>isEligibleForDiscount</code> that isn&#8217;t stored in the model but is derived from its data.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Flattening:</strong> A <code>UserOrderDto</code> might flatten a relationship, taking the <code>orderNumber</code> from an associated <code>OrderModel</code> instead of nesting the entire <code>OrderModel</code> object.</p>
</li>
</ul>
</li>
</ul>
<p class="ds-markdown-paragraph">DTOs often start life as mirrors of Models but are expected to diverge based on external requirements. The Model is stable; the DTO is volatile and adaptable.</p>
<h2>DAOs and Entities: A Direct Mirror</h2>
<p class="ds-markdown-paragraph"><em>DAOs closely match the entity definitions</em></p>
<ul>
<li>
<p class="ds-markdown-paragraph"><strong>This is Almost Always True:</strong> This relationship is much more direct and rigid. A DAO&#8217;s single responsibility is to perform CRUD operations on a specific Entity.</p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>One-to-One Mapping:</strong> You will typically have:</p>
<ul>
<li>
<p class="ds-markdown-paragraph">A <code>UserEntity</code> class.</p>
</li>
<li>
<p class="ds-markdown-paragraph">A <code>UserDao</code> interface (e.g., <code>UserRepository</code> in Spring).</p>
</li>
<li>
<p class="ds-markdown-paragraph">The <code>UserDao</code> will have methods like <code>save(UserEntity entity)</code>, <code>findUserEntityById(Long id)</code>, and <code>delete(UserEntity entity)</code>.</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>The DAO is Contracted to the Entity:</strong> The DAO&#8217;s interface is defined by the structure and relationships of the Entity it manages. Its purpose is to translate that object-oriented structure into persistence commands (SQL, etc.).</p>
</li>
</ul>
<p class="ds-markdown-paragraph">The DAO is fundamentally tied to its corresponding Entity. This is a very strong, one-to-one coupling by design.</p>
<h2>Visualizing the Relationships</h2>
<h3>A Practical Example</h3>
<p><!-- flowchart TD Client["Client"] -- 0 API Request w/JSON data --o Controller["Controller 1 Transforms JSON to DTO"] Controller -- 2 Passes DTO --o Service["Serice 3 Maps DTO to Mode"] Service -- 4 Passes Model mapped to Entity --o DAO["DAO"] DAO -- 5 Saves Entity --o Database[("Database")] Database -- 6 Returns success --o Client --><img data-recalc-dims="1" fetchpriority="high" decoding="async" data-attachment-id="4759" data-permalink="https://cachecrew.com/?attachment_id=4759" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?fit=1459%2C2560&amp;ssl=1" data-orig-size="1459,2560" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Mermaid Chart-2025-09-04-233636" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?fit=584%2C1024&amp;ssl=1" class="wp-image-4759 alignright" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?resize=247%2C433&#038;ssl=1" alt="" width="247" height="433" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?w=1459&amp;ssl=1 1459w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?resize=171%2C300&amp;ssl=1 171w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?resize=584%2C1024&amp;ssl=1 584w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?resize=768%2C1347&amp;ssl=1 768w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?resize=876%2C1536&amp;ssl=1 876w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/09/Mermaid-Chart-2025-09-04-233636-scaled.png?resize=1167%2C2048&amp;ssl=1 1167w" sizes="(max-width: 247px) 100vw, 247px" /></p>
<p class="ds-markdown-paragraph">Imagine an application with a <code>User</code> and a <code>Order</code> model.</p>
<ol>
<li>
<p class="ds-markdown-paragraph"><strong>Persistence Layer:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph"><code>UserEntity</code> (id, username, password_hash, created_date)</p>
</li>
<li>
<p class="ds-markdown-paragraph"><code>OrderEntity</code> (id, user_id, total_amount, status)</p>
</li>
<li>
<p class="ds-markdown-paragraph"><code>UserDao</code> &#8211; methods like <code>save(UserEntity)</code>, <code>findById(id)</code></p>
</li>
<li>
<p class="ds-markdown-paragraph"><code>OrderDao</code> &#8211; methods like <code>save(OrderEntity)</code>, <code>findOrdersByUser(UserEntity)</code></p>
</li>
</ul>
<p class="ds-markdown-paragraph"><em>Here, the DAOs are tightly coupled to their respective Entities.</em></p>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>Business Layer:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph"><code>User</code> model (id, username, password, ordersList, hasPasswordExpired())</p>
</li>
<li>
<p class="ds-markdown-paragraph"><code>Order</code> model (id, totalAmount, status, canBeCancelled())</p>
</li>
</ul>
</li>
<li>
<p class="ds-markdown-paragraph"><strong>API Response:</strong></p>
<ul>
<li>
<p class="ds-markdown-paragraph">You need an API endpoint that returns a user&#8217;s profile along with a summary of their recent orders.</p>
</li>
<li>
<p class="ds-markdown-paragraph">You would create a <code>UserProfileDto</code>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="java">public class UserProfileDto {
    private Long id;
    private String username;
    private List&lt;OrderSummaryDto&gt; recentOrders; // &lt;- Flattened/combined data
}</pre>
</li>
<li>
<p class="ds-markdown-paragraph">This DTO <strong>does not match any single Model</strong>. It combines data from the <code>User</code> model and the <code>Order</code> model and presents it in a tailored structure for the client.</p>
</li>
</ul>
</li>
</ol>
<p class="ds-markdown-paragraph"><strong>Final Takeaway:</strong> Your intuition is spot-on for the data access layer (DAO/Entity mirroring). For the interface layer (DTO/Model), the parallelism is a common starting point, but the strategic value of DTOs is realized when they are allowed to be different from the domain models to meet external demands without polluting the core business logic.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/data-layer-model-entity-dto-and-dao/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4744</post-id>	</item>
		<item>
		<title>Data Transfer Objects and NextJS Server Actions</title>
		<link>https://cachecrew.com/data-transfer-objects-and-nextjs-server-actions/</link>
					<comments>https://cachecrew.com/data-transfer-objects-and-nextjs-server-actions/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Fri, 01 Aug 2025 22:28:02 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[DTO]]></category>
		<category><![CDATA[NextJS]]></category>
		<category><![CDATA[ReactJS]]></category>
		<category><![CDATA[TypeScript]]></category>
		<category><![CDATA[zod]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=4714</guid>

					<description><![CDATA[Next.js server actions can be leveraged to implement the DTO (Data Transfer Object) design pattern to structure and manage data flow between the client and server. What Are Data Transfer Objects (DTO)s? DTOs are objects that define the structure of data being transferred between layers of an application (e.g., client and server). They are typically [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><a href="https://nextjs.org/docs/13/app/api-reference/functions/server-actions">Next.js <strong>server actions</strong></a> can be leveraged to implement the <a href="https://www.baeldung.com/java-dto-pattern"><strong>DTO (Data Transfer Object)</strong> design pattern</a> to structure and manage data flow between the client and server. </p>



<h3 class="wp-block-heading"><strong>What Are Data Transfer Objects (DTO)s?</strong></h3>


<div class="wp-block-image">
<figure class="alignleft size-full is-resized"><a href="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/08/dto_architecture_diagram-5.png?ssl=1"><img data-recalc-dims="1" decoding="async" width="465" height="473" data-attachment-id="4741" data-permalink="https://cachecrew.com/data-transfer-objects-and-nextjs-server-actions/dto_architecture_diagram-5/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/08/dto_architecture_diagram-5.png?fit=465%2C473&amp;ssl=1" data-orig-size="465,473" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="dto_architecture_diagram-5" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/08/dto_architecture_diagram-5.png?fit=465%2C473&amp;ssl=1" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/08/dto_architecture_diagram-5.png?resize=465%2C473&#038;ssl=1" alt="" class="wp-image-4741" style="width:317px;height:auto" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/08/dto_architecture_diagram-5.png?w=465&amp;ssl=1 465w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2025/08/dto_architecture_diagram-5.png?resize=295%2C300&amp;ssl=1 295w" sizes="(max-width: 465px) 100vw, 465px" /></a></figure>
</div>


<p class="wp-block-paragraph">DTOs are objects that define the structure of data being transferred between layers of an application (e.g., client and server). They are typically used to:</p>



<ol class="wp-block-list">
<li><strong>Encapsulate Data</strong>: Define a clear contract for the shape of data being sent or received.</li>



<li><strong>Validate Data</strong>: Ensure that the data conforms to a specific structure.</li>



<li><strong>Decouple Layers</strong>: Abstract the internal structure of the server or database from the client.</li>
</ol>



<h3 class="wp-block-heading"><strong>DTOs with Next.js Server Actions</strong></h3>



<p class="wp-block-paragraph">Server actions in Next.js provide a way to handle server-side logic directly in the application. By using DTOs as interfaces for server actions, you can:</p>



<ol class="wp-block-list">
<li><strong>Standardize Data Contracts</strong>
<ul class="wp-block-list">
<li>Define clear and reusable interfaces for the data sent to and received from server actions.</li>



<li>Ensure consistency across the application.</li>
</ul>
</li>



<li><strong>Improve Type Safety</strong>
<ul class="wp-block-list">
<li>Use TypeScript to enforce the structure of data at compile time.</li>



<li>Reduce runtime errors caused by unexpected data shapes.</li>
</ul>
</li>



<li><strong>Simplify Validation</strong>
<ul class="wp-block-list">
<li>Validate incoming and outgoing data against the DTO structure.</li>



<li>Use libraries like <code>zod</code> or <code>class-validator</code> for runtime validation.</li>
</ul>
</li>



<li><strong>Enhance Maintainability</strong>:
<ul class="wp-block-list">
<li>Centralize data definitions, making it easier to update and refactor the application.</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>How to Implement DTOs with Server Actions in Next.js</strong></h3>



<h4 class="wp-block-heading"><strong>Step 1: Define DTO Interfaces</strong></h4>



<p class="wp-block-paragraph">Create TypeScript interfaces or types to define the structure of the data being transferred.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { z } from "zod";

// Define the DTO schema using zod for runtime validation
export const SheetUserWeightsDTO = z.object({
  userId: z.string(),
  sheetId: z.string(),
  specWeights: z.record(z.string(), z.number()), // Example: { spec1: 0.5, spec2: 0.8 }
  specsVersion: z.number(),
});

// Infer the TypeScript type from the zod schema
export type SheetUserWeightsDTOType = z.infer&lt;typeof SheetUserWeightsDTO>;</pre>



<h4 class="wp-block-heading"><strong>Step 2: Use DTOs in Server Actions</strong></h4>



<p class="wp-block-paragraph">Leverage the DTOs in server actions to validate and enforce the structure of incoming and outgoing data.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { SheetUserWeightsDTO, SheetUserWeightsDTOType } from "@/lib/dto/sheetUserWeights.dto";

export async function saveSheetUserWeightsAction(data: SheetUserWeightsDTOType): Promise&lt;void> {
  // Validate the incoming data
  const parsedData = SheetUserWeightsDTO.parse(data);

  // Perform the server-side logic (e.g., save to database)
  const { userId, sheetId, specWeights, specsVersion } = parsedData;

  // Example: Save to database
  await db.collection("sheetUserWeights").updateOne(
    { userId, sheetId },
    { $set: { specWeights, specsVersion } },
    { upsert: true }
  );
}

export async function getSheetUserWeightsAction(userId: string, sheetId: string): Promise&lt;SheetUserWeightsDTOType | null> {
  // Fetch data from the database
  const result = await db.collection("sheetUserWeights").findOne({ userId, sheetId });

  if (!result) return null;

  // Validate the fetched data
  return SheetUserWeightsDTO.parse(result);
}</pre>



<h4 class="wp-block-heading"><strong>Step 3: Use DTOs in Client-Side Hooks</strong></h4>



<p class="wp-block-paragraph">Use the DTOs in React Query hooks to ensure type safety and consistency.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { SheetUserWeightsDTOType } from "@/lib/dto/sheetUserWeights.dto";
import { getSheetUserWeightsAction, saveSheetUserWeightsAction } from "@/lib/actions/sheets";

export function useQuerySheetUserWeights(userId: string, sheetId: string) {
  return useQuery&lt;SheetUserWeightsDTOType | null, Error>({
    queryKey: ["sheetUserWeights", userId, sheetId],
    queryFn: () => getSheetUserWeightsAction(userId, sheetId),
    enabled: !!userId &amp;&amp; !!sheetId,
    staleTime: 1000 * 60 * 5, // Cache for 5 minutes
  });
}

export function useSaveSheetUserWeights() {
  const queryClient = useQueryClient();

  return useMutation&lt;void, Error, SheetUserWeightsDTOType>({
    mutationFn: saveSheetUserWeightsAction,
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries(["sheetUserWeights", variables.userId, variables.sheetId]);
    },
  });
}</pre>



<h3 class="wp-block-heading"><strong>Benefits of This Approach</strong></h3>



<ol class="wp-block-list">
<li><strong>Type Safety</strong>
<ul class="wp-block-list">
<li>Both the client and server share the same DTO definitions, ensuring consistent data structures.</li>
</ul>
</li>



<li><strong>Validation</strong>:
<ul class="wp-block-list">
<li>DTOs can validate incoming and outgoing data at runtime, catching errors early.</li>
</ul>
</li>



<li><strong>Reusability</strong>:
<ul class="wp-block-list">
<li>DTOs can be reused across server actions, client-side hooks, and even database queries.</li>
</ul>
</li>



<li><strong>Scalability</strong>:
<ul class="wp-block-list">
<li>As the application grows, DTOs provide a clear and maintainable way to manage data contracts.</li>
</ul>
</li>
</ol>



<h3 class="wp-block-heading"><strong>When to Use DTOs</strong></h3>



<ul class="wp-block-list">
<li><strong>Complex Applications</strong>:
<ul class="wp-block-list">
<li>DTOs are especially useful in applications with complex data flows or multiple layers (e.g., client, server, database).</li>
</ul>
</li>



<li><strong>Shared Data Contracts</strong>:
<ul class="wp-block-list">
<li>When the same data structure is used across multiple parts of the application (e.g., client and server).</li>
</ul>
</li>



<li><strong>Validation Requirements</strong>:
<ul class="wp-block-list">
<li>When you need to validate data at runtime to ensure correctness.</li>
</ul>
</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Conclusion</strong></h3>



<p class="wp-block-paragraph">Using DTOs as interfaces for server actions in Next.js is a powerful design pattern that improves type safety, validation, and maintainability. By defining DTOs with tools like <code><a href="https://www.npmjs.com/package/zod">zod</a></code> or TypeScript interfaces, you can standardize data contracts across your application and ensure consistency between the client and server.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">This article was generated mostly via my prompting of AI CoPilot; Image was generated via <a href="https://claude.ai/chat/664f90a3-7fe9-4a6f-b4ec-dec80eb95390">Claude.ai</a>. I had to edit the result. </p>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/data-transfer-objects-and-nextjs-server-actions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4714</post-id>	</item>
		<item>
		<title>Adding Markdown (mdx) Support to NextJS with App Router</title>
		<link>https://cachecrew.com/adding-markdown-mdx-support-to-nextjs-with-app-router/</link>
					<comments>https://cachecrew.com/adding-markdown-mdx-support-to-nextjs-with-app-router/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Fri, 04 Jul 2025 08:18:09 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[NextJS]]></category>
		<category><![CDATA[ReactJS]]></category>
		<category><![CDATA[recipe]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=4689</guid>

					<description><![CDATA[Markdown allows text content to be written with implicit formatting that nearly matches how one would write text without thought of formatting. A lot of web content is also simply text content; a lot of web content is built on the ReactJS library; and NextJS has become a popular framework, extending ReactJS. With that, I [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.markdownguide.org/basic-syntax/">Markdown</a> allows text content to be written with implicit formatting that nearly matches how one would write text without thought of formatting. A lot of web content is also simply text content; a lot of web content is built on the <a href="https://react.dev/">ReactJS library</a>; and <a href="https://nextjs.org/">NextJS</a> has become a popular framework, extending ReactJS. With that, I was motivated to use the Markdown content of my NextJS web app, but I had trouble simply relying on their <a href="https://nextjs.org/docs/pages/guides/mdx">documentation</a>, so I thought I would document what I got working.</p>
<ol>
<li>Use Markdown for a text-heavy <em>portion</em> of a page of my web app, and</li>
<li>To be able to have an entire page of content come from a single Markdown page</li>
</ol>
<p>The former is a feature of NextJS to allow markdown content to be imported as a &#8220;component,&#8221; which can be rendered like any component in ReactJs.</p>
<p>The latter would rely NextJS&#8217;s <a href="https://nextjs.org/docs/app">App Router</a> that assumes many URL paths for the app parallel the file/directory hierarchy of the app itself. So, merely placing a &#8220;page&#8221; file in the app&#8217;s directory will create a new URL path for the website. That means that you can create a &#8220;page.md&#8221; or &#8220;page.mdx&#8221; file with Markdown text content to define the content for that URL. .mdx files also allow JSX syntax so that React/Next components can be embedded within the Markdown.<span id="more-4689"></span></p>
<h2>Setup</h2>
<p>The first issue was getting things set up. Here were the steps that worked for me.</p>
<ol>
<li>Add packages. The highlighted line was missing from the documentation.
<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-highlight="2" data-enlighter-linenumbers="false">npm install @mdx-js/loader @mdx-js/react @next/mdx
npm install -D @types/mdx
</pre>
</li>
<li>In <code>next.config.*</code>, add
<ol>
<li><code>import withMDX from "@next/mdx";</code></li>
<li>Add &#8220;md&#8221; (optional) and &#8220;mdx&#8221; extensions for App Router support: <code>nextConfig.pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx']</code></li>
<li>Create, then wrap the Next config with mdx-config<code>withMDX = createMDX({})</code>…<code>export default withMDX(nextConfig)</code></li>
</ol>
<p>Note: I had to avoid using <code>.ts</code> to avoid syntax errors to support the &#8220;remark-gfm&#8221; plugin. I recommend using <code>.js</code> or <code>.mjs</code> extensions, I chose the latter.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-group="next.config.mjs" data-enlighter-linenumbers="false" data-enlighter-title="Standard">import type {NextConfig} from 'next';

const nextConfig: NextConfig = {
  typescript: {
    ignoreBuildErrors: true,
  },
  eslint: {
    ignoreDuringBuilds: true,
  },
};

export default nextConfig;</pre>
asdfasdf asdf asdf asd f
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-highlight="2,5,14-28" data-enlighter-title="MDX Support" data-enlighter-linenumbers="false" data-enlighter-group="next.config.mjs">import type {NextConfig} from 'next';
import withMDX from "@next/mdx";

const nextConfig: NextConfig = {
  pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
  typescript: {
    ignoreBuildErrors: true,
  },
  eslint: {
    ignoreDuringBuilds: true,
  },
};

const withMdxConfig = withMDX({
  options: {
    remarkPlugins: [],
    rehypePlugins: [],
  },
});

export default withMdxConfig(nextConfig);</pre>
</li>
<li>Add the mdx-components.tsx file to <code>src/</code>. This file allows overriding how tags and components will be rendered, providing a mapping from tag/component name to an overriding render function; see the official documentation, <a href="https://nextjs.org/docs/app/api-reference/file-conventions/mdx-components">mdx-components.js</a>, but I will elaborate on how we&#8217;ll use this in the following sections.
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-linenumbers="false">import type { MDXComponents } from 'mdx/types'

export function useMDXComponents(components: MDXComponents): MDXComponents {
   return {
      ...components,
   }
}
</pre>
</li>
<li>Help VSCode resolve imports
<ol>
<li>Open settings</li>
<li>Search for &#8220;file associations&#8221;</li>
<li>Add item key = <code>*.mdx</code>, value = <code>markdown</code>. (Articles say, &#8220;react-markdown,&#8221; but that didn&#8217;t work for me).</li>
</ol>
</li>
<li>Styles will need to be defined for all the generated HTML tags. See the next sections. </li>
</ol>
<h2>Defining Markdown Output Style</h2>
<p>Markdown syntax is translated to HTML. By default, the HTML tags have had their formatting stripped, for some reason. That means that the tags need to have style/class definitions applied to render properly. See <a href="https://nextjs.org/docs/pages/guides/mdx#using-custom-styles-and-components">How to use markdown and MDX in Next.js</a>, for the official word.</p>
<p>The following are tags that correspond to Markdown syntax:</p>

<figure class="wp-block-table">
<table>
<thead>
<tr>
<th> </th>
<th>Markdown</th>
<th>HTML</th>
</tr>
</thead>
<tbody>
<tr>
<td>Headings</td>
<td><code>#</code> Level 1<br /><code>##</code> Level 2<br /><code>###</code> Level 3<br />&#8230;<br /><code>######</code> Level 6</td>
<td><code>&lt;h1&gt;</code>Level 1<code>&lt;/h1&gt;</code><br /><code>&lt;h2&gt;</code>Level 2<code>&lt;/h2&gt;</code><br /><code>&lt;h3&gt;</code>Level 3<code>&lt;/h3&gt;</code><br />…<br /><code>&lt;h6&gt;</code>Level 6<code>&lt;/h6&gt;</code></td>
</tr>
<tr>
<td>Bold, Italic, Bold Italic</td>
<td><code>*</code> and <code>_</code> are interchangeable<br /><code>**</code>bold<code>**</code> or <code>__</code>bold<code>__</code><br /><code>*</code>italic<code>*</code> or <code>_</code>italic<code>_</code><br /><code>***</code>bold-italic<code>***</code></td>
<td><code>&lt;b&gt;</code>bold<code>&lt;/b&gt;</code><br /><code>&lt;i&gt;</code>italic<code>&lt;/i&gt;</code><br /><code>&lt;b&gt;&lt;i&gt;</code>bold-italic<code>&lt;/i&gt;&lt;/b&gt;</code> or <code>&lt;i&gt;&lt;b&gt;</code>bold-italic<code>&lt;/b&gt;&lt;/i&gt;</code></td>
</tr>
<tr>
<td>Bullet list</td>
<td><code>-</code> Item 1<br /><code>-</code> Item 2</td>
<td><code>&lt;ul&gt;</code><br /><code>&lt;li&gt;</code>Item 1<code>&lt;/li&gt;</code><br /><code>&lt;li&gt;</code>Item 2<code>&lt;/li&gt;</code><br /><code>&lt;/ul&gt;</code></td>
</tr>
<tr>
<td>Ordered list</td>
<td><code>1.</code> Item 1<br /><code>2.</code> Item 2</td>
<td><code>&lt;ol&gt;</code><br /><code>&lt;li&gt;</code>Item 1<code>&lt;/li&gt;</code><br /><code>&lt;li&gt;</code>Item 2<code>&lt;/li&gt;</code><br /><code>&lt;/ol&gt;</code></td>
</tr>
<tr>
<td>Unformatted </td>
<td>
<p><code>```</code><br />unformatted <br />   text<br /><code>```</code></p>
</td>
<td>
<p><code>&lt;pre&gt;</code><br />unformatted<br />  text<br /><code>&lt;/pre&gt;</code></p>
</td>
</tr>
<tr>
<td>Link</td>
<td><code>[</code>description<code>](</code>http://&#8230;<code>)</code></td>
<td><code>&lt;a href="</code>http://&#8230;<code>"&gt;</code>description<code>&lt;/a&gt;</code></td>
</tr>
<tr>
<td>Plain or paragraph text</td>
<td>text &#8230;</td>
<td><code>&lt;p&gt;</code>text &#8230;<code>&lt;/p&gt;</code></td>
</tr>
<tr>
<td>Checkbox (an extended feature supported by the remark-gfm plugin) </td>
<td>
<p><code>- [ ]</code>Incomplete task<br /><code>- [x]</code>Completed task</p>
</td>
<td>
<p><code>&lt;ul class="contains-task-list"&gt;</code><br />  <code>&lt;li class="task-list-item"&gt;&lt;input disabled="" type="checkbox"&gt;</code>Incomplete task<code>&lt;/li&gt;</code><br />  <code>&lt;input disabled="" type="checkbox"&gt;&lt;li class="task-list-item" checked&gt;</code>Completed task<code>&lt;/li&gt;</code><br /><code>&lt;/ul&gt;</code></p>
</td>
</tr>
</tbody>
</table>
</figure>

<p>By default, NextJS removes the styling for the Markdown HTML tags, so we have to define them. </p>
<h3>Wrapper</h3>
<p>Styles and classnames can be defined for any tag and component by redefining it to render with a <code>style</code> or <code>className</code> property, as desired. Instead, we will take advantage of a special Component named &#8220;wrapper&#8221; that wraps any <code>.mdx</code> content and define tag styles within that container context. Then we define all tag&#8217;s styles in an importable CSS module. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-highlight="2,7" data-enlighter-linenumbers="false">import type { MDXComponents } from 'mdx/types'
import styles from './mdx-components.module.css'

export function useMDXComponents(components: MDXComponents): MDXComponents { 
   return { 
      ...components, 
      wrapper: ({ children }) =&gt; &lt;div className={styles.mdxWrapper}&gt;{children}&lt;/div&gt;,
   } 
}</pre>
<p>The file name and the wrapper class names are irrelevant so long as they match. Here is a good starting point for the &#8220;mdx-components.module.css&#8221; that I use. Note the class name, &#8220;_mdxWrapper&#8221; parent style definition. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="css" data-enlighter-linenumbers="false" data-enlighter-title="mdx-components.module.css" data-enlighter-group="&quot;mdx-components.module.css&quot;" data-enlighter-highlight="6">/**
 * Style definitions for tags corresponding to Markdown for MDX components
 * This file provides a reset for common HTML elements used in MDX content
 * to ensure consistent styling.
 */
._mdxWrapper {
  h1, h2, h3, h4, h5, h6, p, blockquote, pre, table {
    display: block;
    margin-block: initial;
    margin-inline: initial;
  }

  h1, h2, h3, h4, h5, h6 { font-weight: bold; }

  h1 {
    border-top: 1px solid lightgray;
    margin-block-start: 0.67em;
    font-size: 2em;
  }
  h2 { margin-block-start: 0.83em; font-size: 1.5em; }
  h3 { margin-block-start: 1em;    font-size: 1.17em; }
  h4 { margin-block-start: 1.67em; font-size: 1em; }
  h5 { margin-block-start: 1.33em; font-size: 0.83em; }
  h6 { margin-block-start: 2.33em; font-size: 0.67em; }

  p { margin-block: 0.4em; }

  a {
    color: -webkit-link;
    text-decoration: underline;
    cursor: pointer;
  }

  ul, ol {
    display: block;
    padding-inline-start: 1.5625rem;
  }
  ul { list-style-type: disc; }
  ul ul { list-style-type: circle; }
  ul ul ul { list-style-type: square; }
  ol { list-style-type: decimal; }
  
  blockquote {
    margin-block: 1em;
    margin-inline: 40px;
  }
  code, pre {
    font-family: monospace;
  }
  pre {
    display: block;
    margin-block: 1em;
    white-space: pre;
  }

  img {
    display: inline-block;
    max-width: 100%;
    height: auto;
  }

  table {
    /* Table styling variables */
    /* --table-border-color: blue; */
    /* --table-border-width: 2px;  */    /* Enable to non-0 to surround table with border */
    /* --table-header-background-color: #f2f2f2; */ /* Enable for distinct header background	color */
    --table-header-border-color: #BBB;   /* Defaults to cell border color */
    --table-header-border-width: 2px;    /* Defaults to row border width */
    --table-body-row-border-width: 1px;  /* Enable to non-0 show row dividers */
    --table-body-col-border-width: var(--table-body-row-border-width,1px);  /* Enable to non-0 show col dividers */
    --table-body-cell-border-color: lightgray;  /* Override border color */
    --table-body-background-color: white;/* Even row background color */
    --table-body-background-color-alt: #f9f9f9; /* Odd row background color */
    margin-left: var(--table-body-row-border-width,0);
    border-collapse: collapse;
    text-indent: initial;
  }
  thead, tbody, tfoot {
    vertical-align: middle;
  }
  thead {
    border-color: var(--table-border-color);
    border-width: var(--table-border-width,0) var(--table-border-width,0) 0 var(--table-border-width,0);
  }
  tbody {
    border-color: var(--table-border-color);
    border-width: 0 var(--table-border-width,0) var(--table-border-width,0) var(--table-border-width,0);
  }
  thead th {
    background-color: var(--table-header-background-color, inherit);
    /* border-style: solid; */
    border-color: var(--table-header-border-color, var(--table-body-cell-border-color));
    border-bottom-width: var(--table-header-border-width,var(--table-body-row-border-width,0));
  }
  tr {
    vertical-align: inherit;
    border: none; /* Disable row borders */
    border-color: inherit;
  }
  td, th {
    /* No top border, conditional side/bottom borders */
    border-width: 0 var(--table-body-col-border-width, 0px) var(--table-body-row-border-width, 0px) var(--table-body-col-border-width, 0px);
    border-color: var(--table-body-cell-border-color);
    padding-inline: 8px;
  }
  /* No side borders */
  td:last-child, th:last-child { border-right: none; }
  td:first-child, th:first-child { border-left: none; }

  /* Alternating background colors for table rows */
  tbody tr:nth-child(odd)  { background-color: var(--table-body-background-color); }
  tbody tr:nth-child(even) { background-color: var(--table-body-background-color-alt); }
} /* ._mdxWrapper */</pre>
<h4>Checkbox Support via &#8220;remark-gfm&#8221;</h4>
<p>Github markup is supported via the remark-gfm plugin, however, I was never able to get it to work as documented (i.e., import and add  <code>remarkGfm</code>  to the plugins array. Instead, I had to use the string name of the plugin and add an array to the plugins array:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-highlight="28" data-enlighter-lineoffset="26" data-enlighter-group="remark-gfm" data-enlighter-title="This works!">const withMdxConfig = withMDX({
  options: {
    remarkPlugins: [['remark-gfm']],
    rehypePlugins: [],
  },
});

export default withMdxConfig(nextConfig);
</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-group="remark-gfm" data-enlighter-title="Supposed to work" data-enlighter-highlight="2,11">import withMDX from "@next/mdx"
import remarkGfm from 'remark-gfm'

const nextConfig: NextConfig = {
  pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"],
}

const withMdxConfig = withMDX({
  options: {
    // If you use remark-gfm, you'll need to use next.config.mjs
    remarkPlugins: [remarkGfm],
    rehypePlugins: [],
  },
})

export default withMdxConfig(nextConfig);
</pre>
<p>The styling for task/checkboxes needs to be set. Unfortunately, remark-gfm uses class names to identify the list and list item tags. Since importing CSS modules mangles names, we have to import the CSS definitions directly. We can create a CSS file, randomly named, &#8220;remark-gfm.css&#8221;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="css" data-enlighter-linenumbers="false">/* remarkGfm MDX Checkbox support for remarkGfm */
ul.contains-task-list li.task-list-item {
  list-style-type: none; /* Remove list style for task list items */
  text-indent: -18px;    /* ...and outdent it so it aligns        */
}
/* Undo &lt;li&gt; inherited styling within nested chckbox lists */
ul.contains-task-list li:not(.task-list-item) {
  list-style-type: initial;
  text-indent: initial;
}
</pre>
<p>Then import this directly into &#8220;mdx-components.tsx.&#8221; Alternatively, you can add these style definitions in global.css.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-highlight="3">import type { MDXComponents } from 'mdx/types'
import styles from './mdx-components.module.css'
import './remark-gfm.css'

export function useMDXComponents(components: MDXComponents): MDXComponents {
   return {
      ...components,
      wrapper: ({ children }) =&gt; &lt;div className={styles._mdxWrapper}&gt;{children}&lt;/div&gt;,
   }
}
</pre>
<p>Note: This style definition will affect all content on the page, even outside an MDX component. </p>
<h2>Summary</h2>
<p>I was led down a bunch of rabbit holes due to NextJS&#8217;s Markdown support not matching the documented steps. With the steps described in this post, others should be able to get it working without the headaches I had to go through.</p>
<ol>
<li>Npm-install mdx support packages</li>
<li>Update VSCode file association settings (optionally)</li>
<li>Update &#8220;next.config.mjs&#8221;</li>
<li>Create src/mdx-components.tsx and import a CSS module to define and wrap tag style definitions</li>
<li>If GitHub markdown support is desired, add the plugin and import CSS definitions into mdx-components.tsx</li>
</ol>
<p>Then you can use Markdown content for App Router pages as <code>page.mdx</code> React components, implicitly.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-group="MDX-usage" data-enlighter-title="App Router: page.mdx" data-enlighter-linenumbers="false"># Page Title

This is an example a NextJS App Router page, written with Markdown syntax. </pre>
<p>&nbsp;</p>
<pre class="EnlighterJSRAW" data-enlighter-language="typescript" data-enlighter-highlight="1,8" data-enlighter-group="MDX-usage" data-enlighter-title="page.tsx use of MDX component" data-enlighter-linenumbers="false">import UpdateContent from "./updates.mdx" // Markdown content

export default async function UpdatesPage() { // App Router page component

return (
  &lt;&gt;
     &lt;h1&gt;Updated News&lt;/h1&gt;
     &lt;UpdateContent/&gt; {/* Render Markdown component */}
  &lt;/&gt;
)
</pre>
<p>&nbsp;</p>]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/adding-markdown-mdx-support-to-nextjs-with-app-router/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4689</post-id>	</item>
		<item>
		<title>Command line Clipboard for macOS, Cygwin, and Linux</title>
		<link>https://cachecrew.com/command-line-clipboard-osx-cygwin/</link>
					<comments>https://cachecrew.com/command-line-clipboard-osx-cygwin/#comments</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Sun, 26 Mar 2023 04:37:53 +0000</pubDate>
				<category><![CDATA[Programming Recipes]]></category>
		<category><![CDATA[Technical]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[CLI]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[command]]></category>
		<category><![CDATA[command-line]]></category>
		<category><![CDATA[copy]]></category>
		<category><![CDATA[Cygwin]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[MacOS]]></category>
		<category><![CDATA[OSX]]></category>
		<category><![CDATA[paste]]></category>
		<category><![CDATA[pasteboard]]></category>
		<guid isPermaLink="false">http://cachecrew.com/?p=300</guid>

					<description><![CDATA[I use the command line a lot, even though I am on a graphical user-interface (GUI) on Windows, macOS, or Linux. And since I&#8217;m lazy, I write a lot of scripts to perform repetitive tasks. I stumbled across macOS commands that allow command line programs to copy/paste between the clipboard that we&#8217;re so used to [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img data-recalc-dims="1" decoding="async" data-attachment-id="571" data-permalink="https://cachecrew.com/command-line-clipboard-osx-cygwin/clipboard/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2013/12/clipboard.png?fit=280%2C280&amp;ssl=1" data-orig-size="280,280" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="clipboard" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2013/12/clipboard.png?fit=280%2C280&amp;ssl=1" class="wp-image-571 alignleft" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2013/12/clipboard.png?resize=182%2C182&#038;ssl=1" alt="" width="182" height="182" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2013/12/clipboard.png?w=280&amp;ssl=1 280w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2013/12/clipboard.png?resize=150%2C150&amp;ssl=1 150w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2013/12/clipboard.png?resize=144%2C144&amp;ssl=1 144w" sizes="(max-width: 182px) 100vw, 182px" />I use the command line a lot, even though I am on a graphical user-interface (GUI) on Windows, macOS, or Linux. And since I&#8217;m lazy, I write a lot of scripts to perform repetitive tasks. I stumbled across macOS commands that allow command line programs to copy/paste between the clipboard that we&#8217;re so used to using.</p>
<h2>macOS <code>pbpaste</code> and <code>pbcopy</code></h2>
<p>macOS has two commands, <code>pbpaste</code> and <code>pbcopy</code>, which &#8220;paste&#8221; from the pasteboard to <code>stdout</code> and copies from <code>stdin</code> to the pasteboard, respectively.<span id="more-300"></span>macOS calls their clipboard a &#8220;pasteboard&#8221;, so the <code>pb</code>&#8230; prefix makes sense.  For the command-line, these will only transfer text content. With these commands, then, you can pipe or redirect content as you would with any other command-line filter.</p>
<p>An example which would use both these commands; say, you are in your browser and want to copy the URL from your browser and use it in a command on the command-line, after copying the URL from the browser, you could run a command like:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-linenumbers="false">curl `pbpaste` | pbcopy
</pre>
<p>The clipboard/pasteboard then contains the output of the curl command of the URL, previously held in the clipboard. You can paste the content into a text editor to see the raw output returned by the URL. (For the uninitiated, those single-quotes (<code>`</code>) are backwards single quotes).</p>
<h2>Linux</h2>
<p>For Linux, install the <a href="https://github.com/astrand/xclip">xclip</a> command:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-linenumbers="false">sudo apt install xclip</pre>
<p>Then, define the aliases to mimic the macOS commands:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-linenumbers="false">if type xclip &amp;&gt;/dev/null; then
  alias pbcopy='xclip -sel clip'
  alias pbpaste='xclip -sel clilp -o'
fi</pre>
<h2>Cygwin</h2>
<p>On Windows, I use <a title="Cygwin: Get that Linux feeling - on Windows" href="http://www.cygwin.com/" target="_blank" rel="noopener">Cygwin</a> for consistent command line capability with macOS and Linux. Having found <code>pbpaste</code> and <code>pbcopy</code> on macOS, I figured similar functionality in Cygwin; but it works differently. They implement a clipboard device at <code>/dev/clipboard</code>. We can create a couple of aliases to make the device act like the macOS commands:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-linenumbers="false">if [ -e /dev/clipboard ]; then
  alias pbcopy='cat &gt;/dev/clipboard'
  alias pbpaste='cat /dev/clipboard'
fi</pre>
<p>With those settings, you can use copy/paste commands in the same fashion as in macOS and write scripts that will work in both environments.</p>
<p><em>3/25/2023 — This post was originally published Dec 3, 2013 and updated to include the Linux solution.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/command-line-clipboard-osx-cygwin/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">300</post-id>	</item>
		<item>
		<title>Bash recipe: Script call-stack</title>
		<link>https://cachecrew.com/bash-script-call-stack/</link>
					<comments>https://cachecrew.com/bash-script-call-stack/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Sun, 26 Mar 2023 03:50:10 +0000</pubDate>
				<category><![CDATA[Programming Recipes]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[recipe]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Shell script]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=2413</guid>

					<description><![CDATA[Here&#8217;s a little recipe for printing a &#8220;call-stack&#8221; for Bash scripts. A call-stack is normally the list of nested function calls. This recipe will utilize the BASH_SOURCE, BASH_LINENO, and FUNCNAME environment variables, set by Bash during script executions, to display a call-stack of one script to another, excluding function calls; this will show only the [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="display: inline-block;"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="2421" data-permalink="https://cachecrew.com/bash-script-call-stack/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73-0687702015307871861359/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73.0687702015307871861359.png?fit=528%2C528&amp;ssl=1" data-orig-size="528,528" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Bash shell" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73.0687702015307871861359.png?fit=528%2C528&amp;ssl=1" class="alignleft wp-image-2421 size-thumbnail" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73.0687702015307871861359.png?resize=150%2C150&#038;ssl=1" alt="Bash logo" width="150" height="150" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73.0687702015307871861359.png?resize=150%2C150&amp;ssl=1 150w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73.0687702015307871861359.png?resize=300%2C300&amp;ssl=1 300w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/kisspng-bash-shell-script-command-line-interface-z-shell-5b3df572212d73.0687702015307871861359.png?w=528&amp;ssl=1 528w" sizes="auto, (max-width: 150px) 100vw, 150px" />Here&#8217;s a little recipe for printing a &#8220;call-stack&#8221; for Bash scripts. A call-stack is normally the list of nested function calls. This recipe will utilize the <code>BASH_SOURCE</code>, <code>BASH_LINENO</code>, and <code>FUNCNAME</code> environment variables, set by Bash during script executions, to display a call-stack of one script to another, excluding function calls; this will show only the invocations of one script to another.<span id="more-2413"></span></div>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">showStack() {
  local i
  for (( i=1; i &lt; ${#BASH_SOURCE[@]}; i++ )); do
    [ "${FUNCNAME[$i]}" = source ] &amp;&amp; echo "  ${BASH_SOURCE[$i]}:${BASH_LINENO[(($i - 1))]}"
  done
}
</pre>
<p>Each of my startup dot-files echo their name when they start, so their call to <code>showStack</code> might look like:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-linenumbers="false">.bash_profile...
.profile...
  /home/bill/.profile:31
  /home/bill/.bash_profile:28
.bashrc...
  /home/bill/.bashrc:30
  /home/bill/.profile:243
  /home/bill/.bash_profile:28
</pre>
<p>The explicit output shows that <code>.bash_profile</code> is started, followed by <code>.profile</code>. In <code>.profile</code>, is a call to <code>showStack</code> which displays the script calls: <code>.bash_profile</code> at line 28 invokes <code>.profile</code>, which, at line 31, calls <code>showStack</code>. Later, <code>.bashrc</code> is invoked and it calls <code>showStack</code> at line 30; it was invoked from <code>.profile</code> at its line 243; which was invoked by <code>.bash_profile</code>&#8216;s line 28.</p>
<p>The three Bash variables, <code>BASH_SOURCE</code>, <code>BASH_LINENO</code>, and <code>FUNCNAME</code>, are arrays whose corresponding elements describe the script files, their line numbers, and function names which make up the call-stack. If the invocation is not contained within a function, then the corresponding <code>FUNCNAME</code> element is set to <code>source</code>.</p>
<h2><code>caller</code> Builtin</h2>
<p>I was aware of the Bash variables and wanted the exercise of figuring them out; but if I&#8217;d queried StackOverflow on the topic, would have revealed other&#8217;s similar solutions; notably, one using Bash&#8217;s builtin command, <code>caller</code>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">showStack() {
  while caller $i; do
    ((i++))
  done
}</pre>
<p>Which, for the same scripts, would output (here, I did not filter for the <code>source</code> entries and includes the function calls):</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-linenumbers="false">.bash_profile...
.profile...
31 source /home/bill/.profile
21 _sourceFiles /home/bill/.bash_profile
25 _sourceDotFiles /home/bill/.bash_profile
30 source /home/bill/.bash_profile
.bashrc...
30 source /home/bill/.bashrc
243 source /home/bill/.profile
21 _sourceFiles /home/bill/.bash_profile
25 _sourceDotFiles /home/bill/.bash_profile
30 source /home/bill/.bash_profile
</pre>
<p>These are well illustrated by <a href="https://gitlab.com/kyb" target="_blank" rel="noopener">@kyb</a> in his <a href="https://gitlab.com/kyb/autorsync/-/blob/master/utils.bash#L84-98" target="_blank" rel="noopener">utils.bash</a> script:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-lineoffset="84">function stacktrace { 
   local i=1
   while caller $i | read line func file; do 
      echodbg "[$i] $file:$line $func()"
      ((i++))
   done
}
function stacktrace2 {
   local i=${1:-1} size=${#BASH_SOURCE[@]}
   ((i&lt;size)) &amp;&amp; echodbg "STACKTRACE"
   for ((; i &lt; size-1; i++)) ;do  ## -1 to exclude main()
      ((frame=${#BASH_SOURCE[@]}-i-2 ))
      echodbg "[$frame] ${BASH_SOURCE[$i]:-}:${BASH_LINENO[$i]} ${FUNCNAME[$i+1]}()"
   done
}
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/bash-script-call-stack/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2413</post-id>	</item>
		<item>
		<title>ChatGPT: What is the common way to parse command line parameters with Rust?</title>
		<link>https://cachecrew.com/chatgpt-what-is-the-common-way-to-parse-command-line-parameters-with-rust/</link>
					<comments>https://cachecrew.com/chatgpt-what-is-the-common-way-to-parse-command-line-parameters-with-rust/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Sat, 04 Mar 2023 10:43:31 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming Recipes]]></category>
		<category><![CDATA[ChatGPT]]></category>
		<category><![CDATA[recipe]]></category>
		<category><![CDATA[Rust]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=2319</guid>

					<description><![CDATA[In Rust, the most common way to parse command-line parameters is by using the std::env::args function, which returns an iterator over the command-line arguments passed to the program. Here&#8217;s an example of how you can use this function to parse command-line arguments: use std::env; fn main() { let args: Vec&#60;String&#62; = env::args().collect(); // The first [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="2442" data-permalink="https://cachecrew.com/chatgpt-what-is-the-common-way-to-parse-command-line-parameters-with-rust/rust_programming_language_black_logosvg_medkict/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?fit=900%2C900&amp;ssl=1" data-orig-size="900,900" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Rust Programming Language" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?fit=900%2C900&amp;ssl=1" class="alignleft wp-image-2442 size-thumbnail" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?resize=150%2C150&#038;ssl=1" alt="Rust Programming Language logo" width="150" height="150" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?resize=150%2C150&amp;ssl=1 150w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?resize=300%2C300&amp;ssl=1 300w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?resize=768%2C768&amp;ssl=1 768w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/rust_programming_language_black_logosvg_mEdKiCT.png?w=900&amp;ssl=1 900w" sizes="auto, (max-width: 150px) 100vw, 150px" />In Rust, the most common way to parse command-line parameters is by using the <code>std::env::args</code> function, which returns an iterator over the command-line arguments passed to the program.<span id="more-2319"></span></p>
<p>Here&#8217;s an example of how you can use this function to parse command-line arguments:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="rust">use std::env;

fn main() {
    let args: Vec&lt;String&gt; = env::args().collect();

    // The first argument is always the path to the executable
    let program_name = &amp;args[0];

    // The rest of the arguments are the ones passed by the user
    let user_args = &amp;args[1..];

    println!("Program name: {}", program_name);

    // Print the user-provided arguments
    for arg in user_args {
        println!("User argument: {}", arg);
    }
}
</pre>
<p>In this example, we use <code>env::args</code> to collect all the command-line arguments into a vector of <code>String</code>s. We then separate the program name (which is always the first argument) from the user-provided arguments by slicing the vector. Finally, we print out the program name and each of the user-provided arguments.</p>
<p>From here, you can parse the user-provided arguments based on their position or by using a library like <a href="https://docs.rs/clap/latest/clap/"><code>clap</code></a> or <code>structopt</code> to define a more complex set of command-line options.</p>
<hr />
<h1>Can I use <code>std::env::args</code> to handle option switches?</h1>
<div class="flex-1 overflow-hidden">
<div class="react-scroll-to-bottom--css-ugzcj-79elbk h-full dark:bg-gray-800">
<div class="react-scroll-to-bottom--css-ugzcj-1n7m0yu">
<div class="flex flex-col items-center text-sm dark:bg-gray-800">
<div class="w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-50 dark:bg-[#444654]">
<div class="text-base gap-4 md:gap-6 m-auto md:max-w-2xl lg:max-w-2xl xl:max-w-3xl p-4 md:py-6 flex lg:px-0">
<div class="relative flex w-[calc(100%-50px)] flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]">
<div class="flex flex-grow flex-col gap-3">
<div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap">
<div class="markdown prose w-full break-words dark:prose-invert light">
<p>You can use <code>std::env::args</code> to handle option switches in Rust. However, it requires more manual parsing and error handling than using a dedicated command-line argument parsing library like <code>clap</code> or <code>structopt</code>.</p>
<p>Here&#8217;s an example of how you could use <code>std::env::args</code> to handle option switches:</p>
<div class="bg-black mb-4 rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans">
<pre class="EnlighterJSRAW" data-enlighter-language="rust">use std::env;

fn main() {
    let args: Vec&lt;String&gt; = env::args().collect();

    let mut verbose = false;
    let mut input_file = String::new();

    for arg in args.iter().skip(1) {
        match arg.as_str() {
            "-v" | "--verbose" =&gt; verbose = true,
            file =&gt; input_file = String::from(file),
        }
    }

    println!("Using input file: {}", input_file);

    if verbose {
        println!("Verbose mode is enabled");
    }
}
</pre>
<p>In this example, we use <code>std::env::args</code> to collect the command-line arguments into a <code>Vec&lt;String&gt;</code>. We then manually parse the arguments by iterating over the vector, checking for option switches using a <code>match</code> expression, and setting the appropriate variables.</p>
</div>
</div>
<p>Note that this example only handles the <code>-v</code> or <code>--verbose</code> switch and a single input file argument. If you need to handle more complex command-line arguments, you will need to add more code for error handling, validation, and parsing.</p>
<p>Overall, while using <code>std::env::args</code> can work for simple command-line arguments, it is recommended to use a dedicated command-line argument parsing library like <code>clap</code> or <code>structopt</code> for more complex command-line interfaces. These libraries provide a more robust, flexible, and maintainable solution for handling command-line arguments.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr />
<div class="w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group dark:bg-gray-800">
<div class="text-base gap-4 md:gap-6 m-auto md:max-w-2xl lg:max-w-2xl xl:max-w-3xl p-4 md:py-6 flex lg:px-0">
<div class="relative flex w-[calc(100%-50px)] flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]">
<div class="flex flex-grow flex-col gap-3">
<h1 class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap">How does <code>clap</code> and <code>structopt</code> differ? When should I use one over the other?</h1>
</div>
</div>
</div>
</div>
<p><code>clap</code> and <code>structopt</code> are two popular Rust crates for parsing command-line arguments. Here are some differences between the two:</p>
<ul>
<li><code>clap</code> provides more flexibility and configurability than <code>structopt</code>. It allows you to define complex command-line interfaces with subcommands, argument groups, default values, and more. <code>structopt</code>, on the other hand, is more opinionated and focuses on providing a concise and easy-to-use interface for parsing simple command-line arguments.</li>
<li><code>clap</code> has a more traditional Rust API, where you define options and arguments separately and manually parse the command-line arguments. <code>structopt</code>, on the other hand, uses a macro-based approach where you define a struct to represent the command-line options, and the crate generates the parsing code for you.</li>
<li><code>structopt</code> has a simpler and more concise syntax than <code>clap</code>. It allows you to define command-line options and arguments using Rust struct field attributes, which makes the code more readable and easier to maintain.</li>
<li><code>clap</code> has more features than <code>structopt</code>, such as support for environment variables, YAML configuration files, and more. <code>structopt</code> focuses on providing a minimal and easy-to-use interface, which makes it more suitable for small to medium-sized projects.</li>
</ul>
<p>When to use <code>clap</code>:</p>
<ul>
<li>If you need to define complex command-line interfaces with subcommands, argument groups, default values, and more.</li>
<li>If you need to integrate your command-line interface with environment variables, YAML configuration files, or other external sources.</li>
<li>If you prefer a more traditional Rust API where you define options and arguments separately and manually parse the command-line arguments.</li>
</ul>
<p>When to use <code>structopt</code>:</p>
<ul>
<li>If you have simple command-line arguments that can be represented using a Rust struct.</li>
<li>If you want a concise and easy-to-use syntax for defining command-line options and arguments.</li>
<li>If you want to minimize the amount of code you write for parsing command-line arguments.</li>
</ul>
<hr />
<div class="flex flex-grow flex-col gap-3">
<div class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap">
<div class="markdown prose w-full break-words dark:prose-invert light">
<h1>How to use <code>structopt</code> to process command-line option switches and arguments</h1>
<p>Here&#8217;s an example of how to use <code>structopt</code> to define and parse command-line options and arguments:</p>
<p>First, add <code>structopt</code> to your <code>Cargo.toml</code> file:</p>
<div class="bg-black mb-4 rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans">
<pre class="EnlighterJSRAW" data-enlighter-language="generic">[dependencies]
structopt = "0.3.21"
</pre>
<p>Next, define a <code>struct</code> to represent your command-line options:</p>
</div>
</div>
<div class="bg-black mb-4 rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans">
<pre class="EnlighterJSRAW" data-enlighter-language="rust">use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(name = "My Rust Program", about = "Does awesome things")]
struct Opt {
    #[structopt(short, long, help = "Sets the level of verbosity")]
    verbose: bool,

    #[structopt(name = "FILE", help = "Sets the input file to use")]
    input_file: String,
}
</pre>
</div>
</div>
<p>In this example, we define a <code>struct</code> named <code>Opt</code> that has two fields: <code>verbose</code>, which is a <code>bool</code> that represents the <code>-v</code> or <code>--verbose</code> command-line option, and <code>input_file</code>, which is a <code>String</code> that represents the <code>FILE</code> positional argument.</p>
<p>We also use the <code>StructOpt</code> derive macro to automatically generate the code for parsing the command-line arguments into an instance of <code>Opt</code>.</p>
<p>Finally, in <code>main</code>, parse the command-line arguments using <code>Opt::from_args()</code>:</p>
<div class="bg-black mb-4 rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 px-4 py-2 text-xs font-sans">
<pre class="EnlighterJSRAW" data-enlighter-language="rust">fn main() {
    let opt = Opt::from_args();

    println!("Using input file: {}", opt.input_file);

    if opt.verbose {
        println!("Verbose mode is enabled");
    }
}
</pre>
<p>In this example, we create an instance of <code>Opt</code> by calling <code>Opt::from_args()</code>, which parses the command-line arguments and returns an instance of <code>Opt</code> with the appropriate values.</p>
</div>
</div>
<p>We can then access the values of the <code>verbose</code> and <code>input_file</code> fields directly on the <code>opt</code> variable.</p>
<p>Note that <code>structopt</code> provides many more options for defining command-line arguments, such as specifying default values, specifying allowed values, and grouping arguments into subcommands. Check out the <code>structopt</code> documentation for more information.</p>
</div>
</div>
</div>
<hr />
<div class="w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group dark:bg-gray-800">
<div class="text-base gap-4 md:gap-6 m-auto md:max-w-2xl lg:max-w-2xl xl:max-w-3xl p-4 md:py-6 flex lg:px-0">
<div class="relative flex w-[calc(100%-50px)] flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]">
<div class="flex flex-grow flex-col gap-3">
<h1 class="min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap">Show me how I should add option/switch parsing</h1>
</div>
<div class="flex justify-between">To add option/switch parsing to your Rust command-line application, you can use a crate like <code>clap</code> or <code>structopt</code>. Here&#8217;s an example of how to use <code>clap</code>:</div>
</div>
</div>
</div>
<p>First, add <code>clap</code> to your <code>Cargo.toml</code> file:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">[dependencies]
clap = "3.0.0"</pre>
<p>Next, use <code>clap</code> to define your command-line options:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="rust">use clap::{App, Arg};

fn main() {
    let matches = App::new("My Rust Program")
        .version("1.0")
        .author("Your Name &lt;you@example.com&gt;")
        .about("Does awesome things")
        .arg(
            Arg::new("input")
                .about("Sets the input file to use")
                .value_name("FILE")
                .index(1)
                .required(true),
        )
        .arg(
            Arg::new("verbose")
                .short('v')
                .long("verbose")
                .about("Sets the level of verbosity"),
        )
        .get_matches();

    let input_file = matches.value_of("input").unwrap();
    let is_verbose = matches.is_present("verbose");

    println!("Using input file: {}", input_file);

    if is_verbose {
        println!("Verbose mode is enabled");
    }
}
</pre>
<p>In this example, we define two command-line options using <code>Arg::new</code>. The first option is a positional argument named <code>input</code> that is required and takes a single value. The second option is a flag named <code>verbose</code> that can be set with either <code>-v</code> or <code>--verbose</code>.</p>
<p>We then use <code>get_matches</code> to parse the command-line arguments and store the results in the <code>matches</code> variable. We can retrieve the values of the <code>input</code> and <code>verbose</code> options using the <code>value_of</code> and <code>is_present</code> methods on the <code>matches</code> object, respectively.</p>
<p>Note that <code>clap</code> provides many more options for defining command-line arguments, such as specifying default values, specifying allowed values, and grouping arguments into subcommands. Check out the <code>clap</code> documentation for more information.</p>
<div class="absolute bottom-0 left-0 w-full border-t md:border-t-0 dark:border-white/20 md:border-transparent md:dark:border-transparent md:bg-vert-light-gradient bg-white dark:bg-gray-800 md:!bg-transparent dark:md:bg-vert-dark-gradient">
<form class="stretch mx-2 flex flex-row gap-3 pt-2 last:mb-2 md:last:mb-6 lg:mx-auto lg:max-w-3xl lg:pt-6">
<div class="relative flex h-full flex-1 md:flex-col">
<div class="flex flex-col w-full py-2 flex-grow md:py-3 md:pl-4 relative border border-black/10 bg-white dark:border-gray-900/50 dark:text-white dark:bg-gray-700 rounded-md shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:shadow-[0_0_15px_rgba(0,0,0,0.10)]"></div>
</div>
</form>
</div>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/chatgpt-what-is-the-common-way-to-parse-command-line-parameters-with-rust/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2319</post-id>	</item>
		<item>
		<title>Ruby RSpec FactoryBot traits and transient via ChatGPT</title>
		<link>https://cachecrew.com/ruby-rspec-factorybot-traits-and-transient-via-chatgpt/</link>
					<comments>https://cachecrew.com/ruby-rspec-factorybot-traits-and-transient-via-chatgpt/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Fri, 16 Dec 2022 02:31:36 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[ChatGPT]]></category>
		<category><![CDATA[FactoryBot]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[RSpec]]></category>
		<category><![CDATA[Ruby]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=2011</guid>

					<description><![CDATA[The following was edited together from a series of questions to ChatGPT on the topic. Currently, I cannot identify sources of the originating content. My role was to edit ChatGPT into the following. FactoryBot RSpec is a testing framework for the Ruby programming language, and FactoryBot (formerly known as Factory Girl) is a library for [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="has-small-font-size wp-block-paragraph"><em>The following was edited together from a series of questions to ChatGPT on the topic. Currently, I cannot identify sources of the originating content. My role was to edit ChatGPT into the following.</em></p>



<p class="wp-block-paragraph"><h1>FactoryBot</h1></p>


<div class="wp-block-image">
<figure class="alignleft size-full is-resized"><a href="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?ssl=1"><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="2445" data-permalink="https://cachecrew.com/ruby-rspec-factorybot-traits-and-transient-via-chatgpt/769141-middle/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?fit=900%2C724&amp;ssl=1" data-orig-size="900,724" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Ruby" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?fit=900%2C724&amp;ssl=1" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?resize=286%2C230&#038;ssl=1" alt="" class="wp-image-2445" width="286" height="230" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?w=900&amp;ssl=1 900w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?resize=300%2C241&amp;ssl=1 300w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2023/03/769141-middle.png?resize=768%2C618&amp;ssl=1 768w" sizes="auto, (max-width: 286px) 100vw, 286px" /></a></figure>
</div>


<p class="wp-block-paragraph">RSpec is a testing framework for the Ruby programming language, and FactoryBot (formerly known as Factory Girl) is a library for creating test data in Ruby. Together, these tools can be used to write unit-tests for a Ruby application.</p>



<p class="wp-block-paragraph">In FactoryBot, a factory is a blueprint for creating test data objects. A factory can define various attributes of the objects it creates, such as the object&#8217;s type, the values of its attributes, and any associations it has with other objects.</p>



<span id="more-2011"></span>



<h2 class="wp-block-heading">Traits</h2>



<p class="wp-block-paragraph">A trait in FactoryBot is a named group of attributes that can be can be applied to a factory, used to create an object. Traits allow you to define common attribute sets that can be shared across multiple factories or used to override the default values in a factory. Instead of having to specify the same attributes every time you create an instance of a factory, you can use a trait to define those attributes once, and then include the trait in any factory that needs those attributes.</p>



<p class="wp-block-paragraph">If you have a factory for creating a user object in your application, this factory might have various attributes for the user, such as their name, email address, and password. You can use a trait to group together a set of attributes that are commonly used together.</p>



<p class="wp-block-paragraph">Here&#8217;s an example of how you might use a trait in your factory:</p>



<pre class="wp-block-code"><code>FactoryBot.define do
  factory :user do
    name 'John Doe'
    email 'johndoe@example.com'
    password 'password'

    trait :admin do
      admin true
    end
  end
end</code></pre>



<p class="wp-block-paragraph">In this example, the <code>:admin</code> trait sets the <code>admin</code> attribute to <code>true</code> for the user object. You can use this trait when creating a user object to specify that the user should be an admin. Here&#8217;s an example:</p>



<pre class="wp-block-code"><code>user = FactoryBot.create(:user, :admin)</code></pre>



<p class="wp-block-paragraph">This will create a new user object with the <code>name</code>, <code>email</code>, <code>password</code>, and <code>admin</code> attributes set. The <code>admin</code> attribute will be <code>true</code> because of the <code>:admin</code> trait.</p>



<p class="wp-block-paragraph">Here&#8217;s an example of how you might use a trait to define a&nbsp;<code>:with_email</code>&nbsp;attribute for a&nbsp;<code>User</code>&nbsp;factory:</p>



<pre class="wp-block-code"><code># Define the trait
RSpec.define_trait :with_email do
  transient do
    email { "user@example.com" }
  end

  after(:build) do |user, evaluator|
    user.email = evaluator.email
  end
end

# Use the trait in a factory
FactoryBot.define do
  factory :user, traits: &#91;:with_email] do
    # other attributes for the user go here
  end
end

# Create an instance of the factory with the trait
user = create(:user, :with_email)</code></pre>



<p class="wp-block-paragraph">In this example, the&nbsp;<code>:with_email</code>&nbsp;trait defines an attribute&nbsp;<code>email</code>&nbsp;with a default value of&nbsp;<code>"user@example.com"</code>, and an&nbsp;<code>after(:build)</code>&nbsp;hook that sets the user&#8217;s&nbsp;<code>email</code>&nbsp;attribute to the value of the&nbsp;<code>email</code>&nbsp;attribute when the factory is built. When you create an instance of the&nbsp;<code>:user</code>&nbsp;factory and include the&nbsp;<code>:with_email</code>&nbsp;trait, the user&#8217;s&nbsp;<code>email</code>&nbsp;attribute will be set to the value defined in the trait.</p>



<p class="wp-block-paragraph">Overall, traits in FactoryBot provide a way to group together commonly used sets of attributes, which can make it easier to create objects in your tests.</p>



<h1 class="wp-block-heading">Transients</h1>



<p class="wp-block-paragraph">A &#8220;transient attribute&#8221; is an attribute that is not saved to the database when an object is created. This can be useful when you want to specify certain values for an object when it is created for a test, but you don&#8217;t want those values to be persisted in the actual database. …are used only for the duration of a factory&#8217;s execution. They can be useful for setting temporary values that are needed for a specific test but are not relevant for the long-term state of the object.</p>



<p class="wp-block-paragraph">To use a transient attribute in a factory, you can define it using the&nbsp;<code>transient</code>&nbsp;method’s block, in a FactoryBot factory. For example, you might define a&nbsp;<code>:admin</code>&nbsp;trait for a&nbsp;<code>User</code>&nbsp;factory that sets the&nbsp;<code>admin</code>&nbsp;attribute to&nbsp;<code>true</code>&nbsp;and the&nbsp;<code>email</code>&nbsp;attribute to a specific value.</p>



<pre class="wp-block-code"><code>FactoryBot.define do
  factory :user do
    transient do
      admin false
    end

    name 'John Smith'
    email 'john@example.com'
    password 'password'
    is_admin admin
  end
end</code></pre>



<p class="wp-block-paragraph">In this example, the <code>admin</code> attribute is a transient attribute that is set to <code>false</code> by default. When an instance of the <code>:user</code> factory is created, the <code>is_admin</code> attribute will be set to the value of the <code>admin</code> transient attribute.</p>



<p class="wp-block-paragraph">Its value can be set using the&nbsp;<code>after(:build)</code>&nbsp;hook, as in:</p>



<pre class="wp-block-code"><code>FactoryBot.define do
  factory :user do
    transient do
      admin false
    end

    after(:build) do |user, evaluator|
      user.admin = evaluator.admin
    end
  end
end</code></pre>



<p class="wp-block-paragraph">You can then use the transient attribute when creating an object using the factory:</p>



<pre class="wp-block-code"><code>user = FactoryBot.create(:user, admin: true)</code></pre>



<p class="wp-block-paragraph">This will create a&nbsp;<code>User</code>&nbsp;object with the&nbsp;<code>admin</code>&nbsp;attribute set to&nbsp;<code>true</code>.</p>



<h2 class="wp-block-heading">after(:build)</h2>



<p class="wp-block-paragraph"><code>after(:build)</code> is a hook that allows you to specify a block of code to be run after an object is built using a factory. The <code>:build</code> symbol refers to the &nbsp;<code>build</code>&nbsp;method provided by FactoryBot, used to create an instance of a model without saving it to the database. The block passed to <code>after(:build)</code> is executed after the object is built, but before it is returned. This allows you to modify the object or perform other actions on it before it is used in your tests.</p>



<p class="wp-block-paragraph">Here&#8217;s an example to customize the behavior of a factory:</p>



<pre class="wp-block-code"><code># Define a factory for a User model
FactoryBot.define do
  factory :user do
    # Set some attributes for the user
    name { "John Smith" }
    email { "john@example.com" }
    password { 'password' }

    # Use the after(:build) hook to customize the user
    after(:build) do |user|
      user.name = 'Jane Smith' if user.email == 'jane@example.com'
    end
  end
end

# Now, when you use the factory to build a new user, it will have the
# attributes specified in the factory as well as the password set to "password"
user = build(:user)</code></pre>



<p class="wp-block-paragraph">The block takes a single parameter, which is the object that has been built by the factory. In this example, the&nbsp;<code>after(:build)</code>&nbsp;block modifies the <code>name</code> attribute of the <code>user</code> object if the <code>email</code> attribute is set to <code>'jane@example.com'</code>.</p>



<p class="wp-block-paragraph">sets the&nbsp;<code>password</code>&nbsp;attribute of the&nbsp;<code>user</code>&nbsp;object, being created by the factory, to the value &#8220;password&#8221;.</p>



<p class="wp-block-paragraph">You can also pass a symbol representing a method to&nbsp;<code>after(:build)</code>&nbsp;instead of a block, like this:</p>



<pre class="wp-block-code"><code>after(:build, &amp;:set_password)</code></pre>



<p class="wp-block-paragraph">This will call the&nbsp;<code>set_password</code>&nbsp;method on the object after it has been built by the factory.</p>



<p class="wp-block-paragraph">You can also define multiple&nbsp;<code>after(:build)</code>&nbsp;blocks in a single factory; each block will be executed in the defined order:</p>



<pre class="wp-block-code"><code>factory :user do
  # define user attributes here

  after(:build) do |user|
    user.password = "password"
  end

  after(:build) do |user|
    user.email = "user@example.com"
  end
end

# create a new user object with the password attribute set to "password" and the email attribute set to "user@example.com"
user = build(:user)</code></pre>



<p class="wp-block-paragraph">Note that the&nbsp;<code>after(:build)</code>&nbsp;is only run when you use the&nbsp;<code>build</code>&nbsp;method to create an instance of the model. It will not be run when you use the&nbsp;<code>create</code>&nbsp;method, which both builds and saves the model to the database. If you want to customize the behavior of a factory when it is used with&nbsp;<code>create</code>, you can use the&nbsp;<code>after(:create)</code>&nbsp;hook instead.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/ruby-rspec-factorybot-traits-and-transient-via-chatgpt/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2011</post-id>	</item>
		<item>
		<title>Frontend Security Recipe Checklist</title>
		<link>https://cachecrew.com/frontend-security-recipes/</link>
					<comments>https://cachecrew.com/frontend-security-recipes/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Tue, 04 Jan 2022 04:24:07 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=1532</guid>

					<description><![CDATA[Even as the number of frontend programming vulnerabilities grows continually, many are not difficult to combat; you simply need to remember to fortify your frontend security against them. Maybe, simply start with the HTML5 Security Cheat Sheet which is what this post set out to do Protect &#60;a href="..." target="_blank"&#62; vulnerability to hacked target page [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Even as the number of frontend programming vulnerabilities grows continually, many are not difficult to combat; you simply need to remember to fortify your frontend security against them.</p>



<ul class="wp-block-list">
<li>Maybe, simply start with the <a href="https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html">HTML5 Security Cheat Sheet</a> which is what this post set out to do</li>
<li>Protect <code>&lt;a href="..." target="_blank"&gt;</code> vulnerability to hacked target page by including <code>rel="noopener noreferrer"</code>. See <a href="https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/">Target=&#8221;_blank&#8221; &#8211; the most underestimated vulnerability ever</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/frontend-security-recipes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1532</post-id>	</item>
		<item>
		<title>Catching the Technology Train, After I&#8217;d Disembarked</title>
		<link>https://cachecrew.com/catching-the-technology-train-after-id-disembarked/</link>
					<comments>https://cachecrew.com/catching-the-technology-train-after-id-disembarked/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Tue, 12 Jun 2018 20:02:38 +0000</pubDate>
				<category><![CDATA[Commentary]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=445</guid>

					<description><![CDATA[Staying away from programming for too long, things change faster than I&#8217;d ever expected. Even with a strong foundation, when things move ahead so quickly, too many things change and it isn&#8217;t as easy to hop back on the train, as I would have thought. Today, I am trying to catch up with technology train [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="2028" data-permalink="https://cachecrew.com/catching-the-technology-train-after-id-disembarked/capitol_corridor_sanjoaquin/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?fit=1400%2C429&amp;ssl=1" data-orig-size="1400,429" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Capitol_Corridor_SanJoaquin" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?fit=1024%2C314&amp;ssl=1" class="aligncenter size-full wp-image-2028" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?resize=1400%2C429&#038;ssl=1" alt="https://www.capitolcorridor.org/wp-content/uploads/2016/04/Capitol_Corridor_SanJoaquin.jpg" width="1400" height="429" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?w=1400&amp;ssl=1 1400w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?resize=300%2C92&amp;ssl=1 300w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?resize=1024%2C314&amp;ssl=1 1024w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/Capitol_Corridor_SanJoaquin.jpg?resize=768%2C235&amp;ssl=1 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></p>
<p>Staying away from programming for too long, things change faster than I&#8217;d ever expected. Even with a strong foundation, when things move ahead so quickly, too many things change and it isn&#8217;t as easy to hop back on the train, as I would have thought. Today, I am trying to catch up with technology train that is web development. How did I become so disconnected?</p>
<ol>
<li>My initial disinterest was that I wasn&#8217;t very interested. With web &#8220;development,&#8221; writing text-markup was not &#8220;programming&#8221; (it still isn&#8217;t). It has taken a couple of decades for web-programming to require the skills of <em>true</em> developers. But it is here, today. In the mean time, I&#8217;d left it behind and as a result, it left me behind.</li>
<li>When I recently started looking at getting into web-development, the landscape was changing and evolving so quickly that it was hard to pin down which of the dozens of technologies to focus on. If I&#8217;d picked Perl, ColdFusion, Ruby, AngularJS, etc.… ”the list is endless” I&#8217;d be an expert in another obsolete technology. However, avoiding a pick, meant that I did not get my hands dirty and did not stay keen about the evolving landscape of web-development.</li>
<li>What I never expected is that it isn&#8217;t just the languages and frameworks which have changed, it is also the technology infrastructure which has changed and, notably, this has changed development workflow.</li>
</ol>
<p>The result is that, not only do I need to learn new languages and their nuances, I even need to learn a new workflow, a new way of <em>doing</em> programming. While I am not starting from scratch, a lot of my prior &#8220;expertise&#8221; is not directly applicable; so it <em>feels</em> like starting from scratch.</p>
<p>I could just stick to the old technologies that I am still expert at, but that isn&#8217;t cutting edge. Still I could do that. Then I wouldn&#8217;t have anything to be stressed about. And, that wouldn&#8217;t be so bad, now would it?</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/catching-the-technology-train-after-id-disembarked/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">445</post-id>	</item>
		<item>
		<title>ReactJS: componentWillReceiveProps() is Dead! (*sniff*)</title>
		<link>https://cachecrew.com/reactjs-componentwillreceiveprops-is-dead/</link>
					<comments>https://cachecrew.com/reactjs-componentwillreceiveprops-is-dead/#respond</comments>
		
		<dc:creator><![CDATA[Bill Lee]]></dc:creator>
		<pubDate>Sun, 22 Apr 2018 01:58:04 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming Recipes]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[ReactJS]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://cachecrew.com/?p=616</guid>

					<description><![CDATA[Things evolve. ReactJS evolves. With version 16.3, there were several changes to the component life-cycle methods. In particular, componentWillReceiveProps is disappearing. In its place, they say, you can use the getDerivedStateFromProps static function. I found this a bit challenging, but I did find an interesting pattern when the component-state was dependent on fetched information. I should mention [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img data-recalc-dims="1" loading="lazy" decoding="async" data-attachment-id="654" data-permalink="https://cachecrew.com/reactjs-componentwillreceiveprops-is-dead/reactjs/" data-orig-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?fit=789%2C789&amp;ssl=1" data-orig-size="789,789" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="ReactJS" data-image-description="" data-image-caption="" data-large-file="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?fit=789%2C789&amp;ssl=1" class=" wp-image-654 alignright" src="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?resize=210%2C210&#038;ssl=1" alt="ReactJS" width="210" height="210" srcset="https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?w=789&amp;ssl=1 789w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?resize=150%2C150&amp;ssl=1 150w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?resize=300%2C300&amp;ssl=1 300w, https://i0.wp.com/cachecrew.com/blog/wp-content/uploads/2018/06/ReactJS-1473435732-1528516038100.png?resize=768%2C768&amp;ssl=1 768w" sizes="auto, (max-width: 210px) 100vw, 210px" />Things evolve. ReactJS evolves. With version 16.3, there were several changes to the component life-cycle methods. In particular, <a href="https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops" target="_blank" rel="noopener"><code>componentWillReceiveProps</code></a> is <a href="https://github.com/reactjs/reactjs.org/issues/721" target="_blank" rel="noopener">disappearing</a>. In its place, they say, you can use the <a href="https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops" target="_blank" rel="noopener"><code>getDerivedStateFromProps</code></a> static function. I found this a bit challenging, but I did find an interesting pattern when the component-state was dependent on fetched information.</p>
<p>I should mention that I had a specific goal to better encapsulate data within the component. While I could pass in all the needed data as properties, that would require the surrounding component know <i>what</i> to pass and how to get it. That shouldn&#8217;t necessarily be necessary; the component knows what it needs and how to retrieve it.</p>
<p>For example, say you have a component which accepts a phone number and displays the phone number and the state that it&#8217;s from. Certainly, you could write a simple component that accepts both pieces of information as properties.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-linenumbers="false">&lt;ShowPhoneLocation number="+12065551212" city="Seattle" /&gt;</pre>
<p>Which might be implemented as:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-linenumbers="false">class ShowPhoneLocation extends React.Component {
  render() {
    return (
      &lt;div&gt;{this.props.number} is from {this.props.city}&lt;/div&gt;
    )
  } // render()
} // class ShowPhoneLocation</pre>
<p>But, since the component should be able to infer the state from the phone number (by its area code), it shouldn&#8217;t be incumbent on its container to know what it is.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-highlight="2-7">class ShowPhoneLocation extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    let location = getCityFromPhone(nextProps.number)
    return {
      city: location
    }
  }
  render() {
    return (
      &lt;div&gt;{this.props.number} is from {this.state.city}&lt;/div&gt;
    )
  } // render()
} // class ShowPhoneLocation</pre>
<p>That&#8217;s all well and good, but what if <code>getCityFromPhone()</code> has to call a web service? We don&#8217;t want <code>getDerivedStateFromProps()</code> to stall, waiting for a response. However, it is static and does not have a <code>this</code> reference to the object for which it is returning state; so an asynchronous <code>fetch</code> doesn&#8217;t know what object&#8217;s state to set. Instead, don&#8217;t wait for the result to save in the state, save the request&#8217;s <code>Promise</code> in the state and update the state, once the promise resolves.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-highlight="1-3,11-18,22-24">function getCityFromPhone(number) {
  return fetch('http://saas.com/get/'+number+'/city') // Returns fetch promise
}
class ShowPhoneLocation extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    let location = getCityFromPhone(nextProps.number)
    return {
      city: location
    }
  }
  componentDidUpdate() {
    let location = this.state.city
    if (location instanceof Promise) {
      this.setState({ city: '...waiting...' })
      location.then(city =&gt; this.setState({ city: city }) )
        .catch(() =&gt; this.setState({ city: 'not found' }) )
    }
  }
  render() {
    return (
      &lt;div&gt;
        {this.props.number} is from {this.state.city instanceof Promise
         ? '...'
        : this.state.city}&lt;/div&gt;
    )
  } // render()
} // class ShowPhoneLocation</pre>
<p>In <code>componentDidUpdate()</code> you can define the completion handlers to set the object&#8217;s state, base on the returned information from the service.</p>
<p>It is a common pattern to perform a <code>fetch</code> in <code>componentDidMount()</code>. The problem is that there may not be enough information to perform the fetch, that early, or the information for the fetch changes after the component has been mounted.</p>
<p>I am going to miss <code>componentWillReceiveProps()</code>… without it, things become a bit more convoluted but it&#8217;s going the way of the Dodo.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cachecrew.com/reactjs-componentwillreceiveprops-is-dead/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">616</post-id>	</item>
	</channel>
</rss>
