<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Moses Gathuku</title>
    <description>The latest articles on Forem by Moses Gathuku (@gathuku).</description>
    <link>https://forem.com/gathuku</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F247726%2F041792ec-ff9e-4acb-a8b2-54e1894ccd81.jpeg</url>
      <title>Forem: Moses Gathuku</title>
      <link>https://forem.com/gathuku</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gathuku"/>
    <language>en</language>
    <item>
      <title>Rails custom validation contexts</title>
      <dc:creator>Moses Gathuku</dc:creator>
      <pubDate>Sun, 24 Apr 2022 19:53:30 +0000</pubDate>
      <link>https://forem.com/gathuku/rails-custom-validation-contexts-11l7</link>
      <guid>https://forem.com/gathuku/rails-custom-validation-contexts-11l7</guid>
      <description>&lt;p&gt;In rails, it is possible to specify when the validation should happen. sometimes you may want to introduce new validation or skip some. Rails &lt;code&gt;on&lt;/code&gt; option helps us achieve this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
 &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
 &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :create&lt;/span&gt; 
 &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:published&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;exclusion: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;on: :update&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above validations: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's not possible to create or update a post without a body&lt;/li&gt;
&lt;li&gt;it will be possible to update a post with a duplicate title &lt;/li&gt;
&lt;li&gt;it will be possible to create a record with published nil &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apart from the commonly used &lt;code&gt;on: :create&lt;/code&gt; and &lt;code&gt;on: :update&lt;/code&gt; rails allow us to provide custom contexts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
 &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; 
 &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :publish&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above example, we are validating &lt;code&gt;published_at&lt;/code&gt; presence &lt;code&gt;on: :publish&lt;/code&gt;. Custom contexts  are triggered explicitly by passing the name of the context to &lt;code&gt;valid?&lt;/code&gt; &lt;code&gt;invalid?&lt;/code&gt; or &lt;code&gt;save&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;post &lt;span class="o"&gt;=&lt;/span&gt; Post.new&lt;span class="o"&gt;(&lt;/span&gt;title: &lt;span class="s2"&gt;"Rails validations"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
post.valid? &lt;span class="c"&gt;# true &lt;/span&gt;
post.valid?&lt;span class="o"&gt;(&lt;/span&gt;context: :publish&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# false &lt;/span&gt;
post.save&lt;span class="o"&gt;(&lt;/span&gt;context: :publish&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rails</category>
    </item>
    <item>
      <title>Testing External APIs with VCR in Rails</title>
      <dc:creator>Moses Gathuku</dc:creator>
      <pubDate>Mon, 17 Feb 2020 18:33:46 +0000</pubDate>
      <link>https://forem.com/gathuku/testing-external-apis-with-vcr-in-rails-488m</link>
      <guid>https://forem.com/gathuku/testing-external-apis-with-vcr-in-rails-488m</guid>
      <description>&lt;p&gt;Testing external APIs can be a time-consuming task, &lt;a href="https://github.com/vcr/vcr"&gt;VCR&lt;/a&gt; is a ruby gem that allows you to record test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  How VCR works?
&lt;/h3&gt;

&lt;p&gt;When we make the first API call the request goes through full request and response cycle. VCR records the API request and response, which it saves as a &lt;code&gt;cassette&lt;/code&gt;. In other words, VCR stubs it for future use. When the test is run again, no API call is made. Instead, VCR stubs the response. The test will run much faster as a result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;VCR works together with &lt;a href="https://github.com/bblimke/webmock"&gt;webmock&lt;/a&gt; a library for stubbing and setting expectations of HTTP requests. Add the latest version of VCR and Webmock in your &lt;code&gt;Gemfile&lt;/code&gt;. Run &lt;code&gt;bundle install&lt;/code&gt; to update dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'vcr'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 5.0'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'webmock'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 3.7'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;gt;= 3.7.6'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Its good to add them in test group gems&lt;/p&gt;

&lt;p&gt;Add them as development dependencies if you are developing a gem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;VCR implements a &lt;a href="https://relishapp.com/vcr/vcr/v/1-6-0/docs/configuration/"&gt;configure&lt;/a&gt; block for different configuration. Add the below block in your &lt;code&gt;test_helper.rb&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;VCR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allow_http_connections_when_no_cassette&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cassette_library_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cassettes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;__dir__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hook_into&lt;/span&gt; &lt;span class="ss"&gt;:webmock&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignore_request&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'DISABLE_VCR'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignore_localhost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_cassette_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;record: :new_episodes&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;allow_http_connections_when_no_cassette&lt;/strong&gt; - allows actual full request and response cycle, when no cassette found.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cassette_library_dir&lt;/strong&gt; - directory where cassettes are stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;hook_into&lt;/strong&gt; - specifies a request stubbing library&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ignore_request&lt;/strong&gt; - default is &lt;code&gt;false&lt;/code&gt; when &lt;code&gt;true&lt;/code&gt; VCR makes full request without using cassettes even if they exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ignore-localhost&lt;/strong&gt; -  prevent VCR from having any affect on localhost requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;default_cassette_options&lt;/strong&gt; - takes a hash that provides defaults for each cassette you use&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing API calls
&lt;/h3&gt;

&lt;p&gt;We are now ready to start testing APIs calls. For demo, purpose lets use &lt;a href="https://jsonplaceholder.typicode.com/"&gt;JSONplaceholder&lt;/a&gt; a fake API for developers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VCRTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_fetch_post&lt;/span&gt;
    &lt;span class="no"&gt;VCR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_cassette&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"get_post"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://jsonplaceholder.typicode.com/posts/1'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the test once and VRC will record in &lt;code&gt;cassette_library_dir&lt;/code&gt; you defined in configure block, for our case &lt;code&gt;cassettes/get_post.yml&lt;/code&gt;. When you run the test again no real connection is made making the process very fast. You may realize the speed when you have very many API endpoints to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are having issues with your cassettes or you need new data you can deletes the cassettes and a new version will be created.&lt;/p&gt;

&lt;p&gt;If you have sensitive information in your responses like API keys. You can filter the keys in your configuration block.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;VCR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
 &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_sensitive_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;API_KEY&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'API_KEY'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you like the blog, share with friends&lt;/p&gt;

&lt;h5&gt;
  
  
  Thanks for reading 🎉 😊
&lt;/h5&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>testing</category>
      <category>vcr</category>
    </item>
    <item>
      <title>Testing Action Mailer in Rails</title>
      <dc:creator>Moses Gathuku</dc:creator>
      <pubDate>Thu, 13 Feb 2020 17:24:42 +0000</pubDate>
      <link>https://forem.com/gathuku/testing-action-mailer-in-rails-278l</link>
      <guid>https://forem.com/gathuku/testing-action-mailer-in-rails-278l</guid>
      <description>&lt;p&gt;Rails provide us with useful test helpers to ActionMailer which helps to easily iterate our design, test if our code queues the right email and our email contains the right content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;After creating a rails app we can generate a new Mailer in our app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails generate mailer NotificationMailer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above command we generate a mailer named &lt;code&gt;NotificationMailer&lt;/code&gt;, this creates:-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A class &lt;code&gt;NotificationMailer&lt;/code&gt; in &lt;code&gt;app/mailers&lt;/code&gt;   directory.&lt;/li&gt;
&lt;li&gt; A class &lt;code&gt;NotificationMailerTest&lt;/code&gt; in &lt;code&gt;test/mailers/notification_mailer_test.rb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A preview class &lt;code&gt;NotificationMailerPreview&lt;/code&gt; in &lt;code&gt;test/mailer/preview/notificaton_mailer_preview.rb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A view directory &lt;code&gt;notification_mailer&lt;/code&gt; in &lt;code&gt;app/views&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Mailer Logic
&lt;/h3&gt;

&lt;p&gt;We are ready to create our first email. To create an email that is sent when users sign up in your application head to &lt;code&gt;NotificationMailer&lt;/code&gt; in &lt;code&gt;app/mailer&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="ss"&gt;from: &lt;/span&gt;&lt;span class="s1"&gt;'info@gathuku.tech'&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;subject: &lt;/span&gt;&lt;span class="s1"&gt;'Welcome to my App'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have defined a welcome method that sends a welcome email. The method accepts the user object as the argument.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note we have defined the &lt;code&gt;default from&lt;/code&gt; at the top of our class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Mailer view
&lt;/h3&gt;

&lt;p&gt;After writing our logic remember &lt;code&gt;notification_mailer&lt;/code&gt; directory that was created in our &lt;code&gt;app/view&lt;/code&gt;, head into the directory and create a file named &lt;code&gt;welcome.erb.html&lt;/code&gt;. The file will render HTML design for our email.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note the naming convention. The name must match the name of our email method.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- &amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en" dir="ltr"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8"&amp;gt;

  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Thanks for signing,&amp;lt;%= @user.email %&amp;gt; &amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;Welcome to the app&amp;lt;/p&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt; --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mailer Preview
&lt;/h3&gt;

&lt;p&gt;Remember the preview file that was created? Mailer preview enables us to preview our email design. This is helpful since we don't have to send the actual email to see our email design.&lt;br&gt;
All we need is to define a method that implements our mailer.  &lt;code&gt;notification_mailer_preview.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationMailerPreview&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Preview&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
    &lt;span class="no"&gt;NotificationMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this ensure your server is running and navigate to route &lt;code&gt;http://localhost:3000/rails/mailers&lt;/code&gt;. All your mailers and specific email methods will be listed. Click &lt;code&gt;welcome&lt;/code&gt; to view the welcome email design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Your mailers class just like any other part of Rails application should be tested to ensure they are working properly.&lt;br&gt;
Why should you test your mailers? below are some of the reasons.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To ensure that emails are being processed (created and sent).&lt;/li&gt;
&lt;li&gt;To ensure that the email content is correct (subject, sender, body, etc).&lt;/li&gt;
&lt;li&gt;To ensure the right emails are being sent at the right times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are two aspects of testing mailers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Units tests&lt;/li&gt;
&lt;li&gt;Functional tests&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Units tests
&lt;/h4&gt;

&lt;p&gt;In unit tests, we run the mailer in isolation with tightly controlled inputs and compare the output to a known value (a fixture.)&lt;br&gt;
 In our &lt;code&gt;NotificationMailer&lt;/code&gt; we have &lt;code&gt;welcome&lt;/code&gt; action which is used to send a welcome email when users sign up. Below is the unit test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt; &lt;span class="c1"&gt;# frozen_string_literal: true&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'test_helper'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationMailerTest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestCase&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:one&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s1"&gt;'welcome'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;NotificationMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert_emails&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deliver_later&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'info@gathuku.tech'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Welcome to my App'&lt;/span&gt;
    &lt;span class="n"&gt;assert_match&lt;/span&gt; &lt;span class="s1"&gt;'Thanks for signing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encoded&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the test above, we create the email and store the returned object in the email variable. We then ensure that it was sent (the first assert), then, in the second batch of assertions, we ensure that the email does indeed contain what we expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;To understand more about mailers. The line &lt;code&gt;ActionMailer::Base.delivery_method = :test&lt;/code&gt; in &lt;code&gt;config/environments/test.rb&lt;/code&gt; sets the delivery method to test mode so that email will not be delivered (useful to avoid spamming your users while testing) but instead, it will be appended to an array (&lt;code&gt;ActionMailer::Base.deliveries&lt;/code&gt;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can clear the deliveries array with &lt;code&gt;ActionMailer::Base.deliveries.clear&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
