<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Brena Monteiro</title>
    <description>The latest articles on DEV Community by Brena Monteiro (@monteirobrena).</description>
    <link>https://dev.to/monteirobrena</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%2F288256%2Fb5eb32d1-d143-4423-9fbc-1f9ae2186699.jpg</url>
      <title>DEV Community: Brena Monteiro</title>
      <link>https://dev.to/monteirobrena</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/monteirobrena"/>
    <language>en</language>
    <item>
      <title>Diving into Custom Exceptions in Ruby</title>
      <dc:creator>Brena Monteiro</dc:creator>
      <pubDate>Wed, 05 Apr 2023 14:15:42 +0000</pubDate>
      <link>https://dev.to/appsignal/diving-into-custom-exceptions-in-ruby-2icg</link>
      <guid>https://dev.to/appsignal/diving-into-custom-exceptions-in-ruby-2icg</guid>
      <description>&lt;p&gt;Customizing exceptions is usually not a common concern during software development. But if you catch an error in an observability tool and can't correctly and quickly identify the problem, you may need more information and details about an exception.&lt;/p&gt;

&lt;p&gt;This article will show you how to customize exceptions in Ruby and mitigate potential future problems due to a lack of error information.&lt;/p&gt;

&lt;p&gt;Let's dive straight in!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Side-Note
&lt;/h2&gt;

&lt;p&gt;This post is a natural progression to &lt;a href="https://blog.appsignal.com/2022/09/21/debugging-in-ruby-with-appsignal.html"&gt;Debugging in Ruby with AppSignal&lt;/a&gt;, so we recommend reading that first for an overview of debugging and an introduction to custom exceptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Rescue an Exception with Ruby
&lt;/h2&gt;

&lt;p&gt;Ruby has a class called &lt;code&gt;Exception&lt;/code&gt;, from which error-handling classes inherit. In this section, we'll better understand Ruby's structural exception flow before we create our custom exception.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Exception&lt;/code&gt; is the main exception class in Ruby, and &lt;code&gt;rescue Exception&lt;/code&gt; will catch all exceptions inherited from &lt;code&gt;Exception&lt;/code&gt;. It isn't best practice to use this in our app, as it will catch all exceptions used internally by Ruby.&lt;/p&gt;

&lt;p&gt;The easiest way to rescue an exception in Ruby is to create a &lt;code&gt;begin ... rescue&lt;/code&gt; block of code like the example below:&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;begin&lt;/span&gt;
  &lt;span class="n"&gt;call_some_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="o"&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;Since &lt;code&gt;Exception&lt;/code&gt; will catch all exceptions, we should try to use something more specific to filter and get only the error we want. One example is the &lt;code&gt;StandardError&lt;/code&gt; class, a standard rescuer used to catch exceptions related to application code errors by ignoring Ruby's internal exceptions.&lt;/p&gt;

&lt;p&gt;To catch a &lt;code&gt;StandardException&lt;/code&gt;, you can use the example below:&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;begin&lt;/span&gt;
  &lt;span class="n"&gt;call_some_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardException&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="o"&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;Or, if no exception class is stated, Ruby will return the exceptions handled by the &lt;code&gt;StandardException&lt;/code&gt; class.&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;begin&lt;/span&gt;
  &lt;span class="n"&gt;call_some_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="o"&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;To create a custom exception with Ruby, you'll probably create a class that inherits from &lt;code&gt;StandardError&lt;/code&gt;. We'll cover that in the next few sections.&lt;/p&gt;

&lt;p&gt;To learn more about exceptions and find the best one to inherit, check &lt;a href="https://ruby-doc.org/core-2.5.0/Exception.html"&gt;Ruby's exceptions list&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Additional Information to the Ruby Exception
&lt;/h2&gt;

&lt;p&gt;Creating a new exception without sending relevant information will not effectively help in debugging — identifying and fixing — the problem. You need to add the error details. Here, we will see how to pass information from objects to the custom exception.&lt;/p&gt;

&lt;p&gt;Let's create a new custom exception just to receive the data we want to log. As mentioned in the previous section, the custom exception needs to inherit from &lt;code&gt;StandardError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can use a simple Rails project to test this implementation. Create a new folder called &lt;code&gt;exceptions&lt;/code&gt; inside the &lt;code&gt;app&lt;/code&gt; folder and a class called &lt;code&gt;custom_exception.rb&lt;/code&gt; in your Rails project.&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;# app/exceptions/custom_exception.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomException&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
    &lt;span class="vi"&gt;@msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
    &lt;span class="vi"&gt;@details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this exception class, we can define all the information that needs to be shown in the logs and we use four attributes for our data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a code to enumerate the exception&lt;/li&gt;
&lt;li&gt;a name&lt;/li&gt;
&lt;li&gt;an informational message&lt;/li&gt;
&lt;li&gt;internal information details about the exception already provided by Ruby&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now we create a &lt;code&gt;begin...rescue&lt;/code&gt; block to raise the &lt;code&gt;CustomException&lt;/code&gt; and pass the parameters to the exception attributes.&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;# app/models/employee.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_fees&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt; &lt;span class="c1"&gt;# Any code that throws an exception.&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CustomException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;333&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"My customized exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"A new exception occurred in the application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;exception&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;This looks useful, so let's continue the implementation and use this data to customize the exception log.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending an Exception in Ruby
&lt;/h2&gt;

&lt;p&gt;Extending an exception allows us to elevate customization to a more specific and reusable level. Just as Ruby has several exceptions for different types of errors, we can also follow this line of programming in our systems.&lt;/p&gt;

&lt;p&gt;Next, let's understand how to override our exception and use it in a context that demands an extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.appsignal.com/tour/log-management"&gt;Finding information in logs&lt;/a&gt; is a painful activity. Developers often blame themselves for not including more information about errors or how to search and filter. If you are not using any &lt;a href="https://www.appsignal.com/ruby"&gt;monitoring tools that provide this&lt;/a&gt;, including meaningful data could save you in the foreseeable future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro-tip&lt;/strong&gt;: &lt;em&gt;Check out the section on 'Debugging Exceptions in Ruby with AppSignal' in our post &lt;a href="https://blog.appsignal.com/2022/09/21/debugging-in-ruby-with-appsignal.html"&gt;Debugging in Ruby with AppSignal&lt;/a&gt; for information about how to set up and track custom exceptions in AppSignal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the example below, we will customize the display of exceptions in the log. Initially, you might think that it's just a light and pretty way to show data. However, the keywords used in the data are key to finding an error and helping whoever will be monitoring the application.&lt;/p&gt;

&lt;p&gt;Add the &lt;a href="https://github.com/fazibear/colorize"&gt;colorize&lt;/a&gt; gem to your project by including the code below in your Gemfile.&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;# Gemfile&lt;/span&gt;

&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'colorize'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the bundle to install the colorize gem and launch your Rails application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rails s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in your exception class, import the gem. Print the attributes in a formatted way, so it's easy to see and quickly find an important error.&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;# app/exceptions/custom_exception.rb&lt;/span&gt;

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

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomException&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;log_exception&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_exception&lt;/span&gt;
    &lt;span class="n"&gt;print_separator&lt;/span&gt;

    &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"🚨🚨🚨 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 🚨🚨🚨"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="kp"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# All attributes will be printed.&lt;/span&gt;
      &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="kp"&gt;attr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;print_separator&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_separator&lt;/span&gt;
    &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;color: :black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;background: :red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="no"&gt;STDERR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_s&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:red&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;Check out the result of this visual customization and test some options to create your format and style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WRuhk2Ez--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2023-03/custom-exception.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WRuhk2Ez--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2023-03/custom-exception.png" alt="Custom Exception" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up and Next Steps
&lt;/h2&gt;

&lt;p&gt;In this post, we covered how to customize and highlight a Ruby exception in your logs. Many other customizations are possible, but what's most important is that you handle the exceptions relevant to your application. And remember, don't apply the same formatting style to all exceptions, as Rails already does.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S. If you'd like to read Ruby Magic posts as soon as they get off the press, &lt;a href="https://blog.appsignal.com/ruby-magic"&gt;subscribe to our Ruby Magic newsletter and never miss a single post&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Improve Code in Your Ruby Application with RubyCritic</title>
      <dc:creator>Brena Monteiro</dc:creator>
      <pubDate>Wed, 26 Oct 2022 12:02:12 +0000</pubDate>
      <link>https://dev.to/appsignal/improve-code-in-your-ruby-application-with-rubycritic-mbe</link>
      <guid>https://dev.to/appsignal/improve-code-in-your-ruby-application-with-rubycritic-mbe</guid>
      <description>&lt;p&gt;RubyCritic provides visual reports highlighting code smells, code structure, ease of testing, and test coverage in your Ruby application.&lt;/p&gt;

&lt;p&gt;It's in active development, with new code analysis tools often being introduced as new features. It's well worth keeping track of RubyCritic's releases.&lt;/p&gt;

&lt;p&gt;This article will touch on some of RubyCritic's benefits, its dependencies, and how to read its code reports.&lt;/p&gt;

&lt;p&gt;Let's get going!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Choose RubyCritic for Your Ruby on Rails Application?
&lt;/h2&gt;

&lt;p&gt;You should consider using &lt;a href="https://github.com/whitesmith/rubycritic"&gt;RubyCritic&lt;/a&gt; if you want a single place to review code improvements for your project. Including RubyCritic in your development process will certainly reduce the time a development team spends working on technical debts. Most technical debts will be mapped out at development time.&lt;/p&gt;

&lt;p&gt;Some benefits that RubyCritic can provide to your project and development process include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unified information in one place&lt;/li&gt;
&lt;li&gt;Visual reports&lt;/li&gt;
&lt;li&gt;Easy installation&lt;/li&gt;
&lt;li&gt;Zero configuration&lt;/li&gt;
&lt;li&gt;Customization allowed&lt;/li&gt;
&lt;li&gt;Being extensible — you can make your own open-source integration&lt;/li&gt;
&lt;li&gt;A badge generator 🎉&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To understand how RubyCritic works, let's look at the internal dependencies it uses to make reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal Dependencies in RubyCritic
&lt;/h2&gt;

&lt;p&gt;When you add RubyCritic to your project, some dependencies will also be included.&lt;/p&gt;

&lt;p&gt;Let's highlight the dependencies that make magic happen: the Reek, Flay, and Flog gems. These dependencies allow RubyCritic to show you valuable information about your code. Understanding how they work also makes RubyCritic easier to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reek: Detect Code Smells in Ruby
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/troessner/reek"&gt;Reek&lt;/a&gt; is a gem for detecting code smells in Ruby. A bad smell in code is not about identifying wrong code, it is more about analyzing if the code could be written better.&lt;/p&gt;

&lt;p&gt;Reek's analysis identifies &lt;em&gt;if&lt;/em&gt; something could be implemented in another way. It does not suggest &lt;em&gt;how&lt;/em&gt;, as most code smells are associated with business logic and a developer's experience with a language.&lt;/p&gt;

&lt;p&gt;For example, you could easily rewrite an &lt;code&gt;if&lt;/code&gt; statement using metaprogramming techniques. The way to correct it, though, is up to a developer according to a project's context. In this case, no library will be able to indicate the best solution.&lt;/p&gt;

&lt;p&gt;Reek detects an &lt;a href="https://github.com/troessner/reek/blob/master/docs/Code-Smells.md"&gt;extensive list of smells&lt;/a&gt;. It examines and identifies possible smells in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classes&lt;/li&gt;
&lt;li&gt;Attributes&lt;/li&gt;
&lt;li&gt;Methods&lt;/li&gt;
&lt;li&gt;Parameters&lt;/li&gt;
&lt;li&gt;Modules&lt;/li&gt;
&lt;li&gt;Iterators&lt;/li&gt;
&lt;li&gt;The implementation of polymorphism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By finding smells, you can take steps to make your code more readable and maintainable.&lt;/p&gt;

&lt;p&gt;Reek allows for custom configuration to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disable a detector by its type&lt;/li&gt;
&lt;li&gt;Exclude directories from being scanned&lt;/li&gt;
&lt;li&gt;Use filters to silence warnings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even define specific code to &lt;a href="https://github.com/troessner/reek/blob/master/docs/Smell-Suppression.md"&gt;suppress in a scan&lt;/a&gt;, a very useful feature when code is not yet finalized or refactored, or even if it is legacy code.&lt;/p&gt;

&lt;p&gt;Let's see a sample of how Reek works. In this code, the exception is just defined as &lt;code&gt;e&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="c1"&gt;# app/controllers/erp/orders_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;

  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ValidationError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;type: &lt;/span&gt;&lt;span class="s2"&gt;"invalid-schema"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s2"&gt;"Your request does not match the expected schema."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;detail: &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;message&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;It is easy to imagine that &lt;code&gt;e&lt;/code&gt; means an exception, but what if we have other exceptions? Identifying them correctly is the best way to maintain good code.&lt;/p&gt;

&lt;p&gt;Reek will identify &lt;code&gt;e&lt;/code&gt; as UncommunicativeVariableName and show a warning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;reek app/controllers/erp/orders_controller.rb
Inspecting 1 file&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;:
S

app/controllers/erp/orders_controller.rb &lt;span class="nt"&gt;--&lt;/span&gt; 1 warning:

  &lt;span class="o"&gt;[&lt;/span&gt;91]:UncommunicativeVariableName: Erp::OrdersController#create has the variable name &lt;span class="s1"&gt;'e'&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://github.com/troessner/reek/blob/v6.1.1/docs/Uncommunicative-Variable-Name.md]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Flay: Check for Ruby Code Duplication
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ruby.sadi.st/Flay.html"&gt;Flay&lt;/a&gt; identifies structural Ruby code similarities, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detecting code duplication within a project&lt;/li&gt;
&lt;li&gt;Checking the difference at any code level&lt;/li&gt;
&lt;li&gt;Generating a score to measure how good your code is (the lower your score, the better the code)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Flay reports a similarity in your code, it's a high indicator that refactoring is needed. Don't ignore this! Duplicate code is a gateway to bugs. If you fix something in one place but forget about another, more bugs appear.&lt;/p&gt;

&lt;p&gt;We can check how Flay works by running it in its own source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flay lib/flay.rb
Total score &lt;span class="o"&gt;(&lt;/span&gt;lower is better&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 36

1&lt;span class="o"&gt;)&lt;/span&gt; Similar code found &lt;span class="k"&gt;in&lt;/span&gt; :iter &lt;span class="o"&gt;(&lt;/span&gt;mass &lt;span class="o"&gt;=&lt;/span&gt; 36&lt;span class="o"&gt;)&lt;/span&gt;
  lib/flay.rb:80
  lib/flay.rb:105
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flay identifies similarities between these two:&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;# lib/flay.rb:80&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-m"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--mass MASS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Sets mass threshold (default = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mass&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;&lt;span class="p"&gt;)&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;m&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:mass&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# lib/flay.rb:105&lt;/span&gt;
&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--timeout TIME"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Set the timeout. (default = &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;&lt;span class="p"&gt;)&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;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the code's spelling is not exactly the same, but its functionality is and can be refactored to avoid duplication. That's the magic of Flay!&lt;/p&gt;

&lt;h3&gt;
  
  
  Flog: Examine Your Code Complexity in Ruby
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ruby.sadi.st/Flog.html"&gt;Flog&lt;/a&gt; checks how difficult your code is to test. It sets a complexity score for each line of code and sums up the score for each method and class.&lt;/p&gt;

&lt;p&gt;The higher the score, the more your code needs to be refactored because it signifies that you have a highly complex implementation.&lt;/p&gt;

&lt;p&gt;Let's see Flog in action! A small change can cause your score to variate.&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;def&lt;/span&gt; &lt;span class="nf"&gt;validate_expiration&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exp_month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;exp_year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flog app/models/credit_card.rb

5.2: CreditCard#validate_expiration   app/models/credit_card.rb:12-15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in the first part of the code, we have an &lt;code&gt;or&lt;/code&gt; check that increases the score by 0.4 points.&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;def&lt;/span&gt; &lt;span class="nf"&gt;validate_expiration&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exp_month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exp_year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flog app/models/credit_card.rb

4.8: CreditCard#validate_expiration app/models/credit_card.rb:12-15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Other RubyCritic Dependencies
&lt;/h3&gt;

&lt;p&gt;RubyCritic also uses other runtime dependencies, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/deivid-rodriguez/byebug"&gt;&lt;code&gt;byebug&lt;/code&gt;&lt;/a&gt; - this elevates debugging Ruby applications. It allows you to run a program line by line, add breakpoints, and evaluate and track values at runtime. If you still use &lt;code&gt;puts&lt;/code&gt; for debugging, it's time you get to know Byebug's features and commands.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/rubocop/rubocop"&gt;&lt;code&gt;rubocop&lt;/code&gt;&lt;/a&gt; - a linter for Ruby code that helps you follow a style guide used by the Ruby community, or even apply your own code style. It's very useful to set standards in your team and avoid silly conflicts about spaces and tabs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/simplecov-ruby/simplecov"&gt;&lt;code&gt;SimpleCov&lt;/code&gt;&lt;/a&gt; - a tool to check Ruby application code coverage. You can configure it to run alongside your tests. It provides metrics on code coverage so that you can identify what you need to pay attention to and where to invest your time to create better test cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/whitesmith/rubycritic/blob/main/rubycritic.gemspec"&gt;Dive into RubyCritic's list of dependencies&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using RubyCritic for Your Ruby on Rails App
&lt;/h2&gt;

&lt;p&gt;RubyCritic has good documentation to help you get started without much configuration. Therefore, we will focus on utilizing its resources to help us analyze its reports.&lt;/p&gt;

&lt;p&gt;RubyCritic provides 'Code', 'Smells', and 'Coverage' reports. We'll look at each of these features in turn.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Overview in RubyCritic
&lt;/h3&gt;

&lt;p&gt;The 'Overview' page shows a total score for your project on a donut chart, along with ratings (A being the best rating, F the worst). The 'Summary' section shows the details of each rating, including the number of files, churns (commit changes), and smells found.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qRxAwCl1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/overview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qRxAwCl1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/overview.png" alt="RubyCritic Overview" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the 'Churn vs Complexity' section here, it is already possible to identify the class with the greatest complexity, which should probably be the first point of attention.&lt;/p&gt;

&lt;p&gt;To better understand this graph, it is worth recapping &lt;a href="https://www.oreilly.com/library/view/making-software/9780596808310/ch23s03.html"&gt;code churn&lt;/a&gt;. Code that changes frequently can raise an alert that something is wrong — maybe in the logic or the business domain, for example. Either way, looking at 'Churn vs Complexity' can help you see where the pain points are across your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Report
&lt;/h3&gt;

&lt;p&gt;The 'Code' report shows a score for each class, including indicators for churn, complexity, duplication, and smells.&lt;/p&gt;

&lt;p&gt;You can sort this list by any column to view the highest ranking factors and address the most critical issues first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5h25ozwb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5h25ozwb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/code.png" alt="RubyCritic Overview" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, this list has a filter that allows you to search by class name quickly.&lt;/p&gt;

&lt;p&gt;Clicking on the class name will open a detailed page with the class code and metrics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code line&lt;/li&gt;
&lt;li&gt;Quantity methods&lt;/li&gt;
&lt;li&gt;Calculated churn&lt;/li&gt;
&lt;li&gt;Complexity by method&lt;/li&gt;
&lt;li&gt;Complexity score (total per class)&lt;/li&gt;
&lt;li&gt;Amount of duplicates found&lt;/li&gt;
&lt;li&gt;Number of smells&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The line of code where an issue is found will be highlighted (based on information provided by the Reek gem).&lt;/p&gt;

&lt;p&gt;If Flog identifies any issues, you'll see a score. You'll also see if a Flay report has detected any duplicate code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IR7MfRhc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/reports.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IR7MfRhc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/reports.png" alt="RubyCritic Overview" width="800" height="785"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Smells Report
&lt;/h3&gt;

&lt;p&gt;The 'Smells' page displays the smell type, the exact location where a smell appears, and the fix status.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, the smells are detected by Reek, and sorting and filtering are also available on this page.&lt;/p&gt;

&lt;p&gt;Clicking on a class name will open a page with your code details. You can also see the classes grouped by smell type (this is missing from the 'Code' page, which only displays the number of smells).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_Fe1BU1l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/smells.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_Fe1BU1l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/smells.png" alt="RubyCritic Overview" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Coverage Report
&lt;/h3&gt;

&lt;p&gt;Finally, you can see class classifications and the percentage of coverage for each class in the 'Coverage' report. In contrast to the lists on the 'Code' and 'Smells' reports, the list in 'Coverage' does not allow information to be sorted and filtered.&lt;/p&gt;

&lt;p&gt;You can only see the percentage of code coverage — no additional information is available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JZVuoH0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/coverage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JZVuoH0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-10/coverage.png" alt="RubyCritic Overview" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Integrating the SimpleCov report could add more value and usefulness to this page. But in any case, the 'Coverage' report can help if you need a simple report to examine your project's test coverage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;In this post, we briefly looked at the benefits of RubyCritic for your Ruby application before diving into its internal dependencies: Reek, Flay, and Flog. We then ran through how to read and analyze RubyCritic's reports.&lt;/p&gt;

&lt;p&gt;As a next step, figure out how to use RubyCritic in your pipeline.&lt;/p&gt;

&lt;p&gt;Happy code refactoring!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S. If you'd like to read Ruby Magic posts as soon as they get off the press, &lt;a href="https://blog.appsignal.com/ruby-magic"&gt;subscribe to our Ruby Magic newsletter and never miss a single post&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Debugging in Ruby with AppSignal</title>
      <dc:creator>Brena Monteiro</dc:creator>
      <pubDate>Wed, 28 Sep 2022 14:38:08 +0000</pubDate>
      <link>https://dev.to/appsignal/debugging-in-ruby-with-appsignal-3g1h</link>
      <guid>https://dev.to/appsignal/debugging-in-ruby-with-appsignal-3g1h</guid>
      <description>&lt;p&gt;An application monitoring tool (APM) is not just useful for seeing how your application performs through graphs and visuals. We can go deeper and use an APM to understand how your application behaves in a certain environment.&lt;/p&gt;

&lt;p&gt;As developers, we should aim to be less reactive to errors and more predictive, avoiding crashes for end-users.&lt;/p&gt;

&lt;p&gt;One way to accomplish this is by using monitoring tools to debug our application when an error occurs. AppSignal has advanced features that allow us to intelligently debug our logs and thus reflect this precautionary thinking in our applications.&lt;/p&gt;

&lt;p&gt;This article will show you how to better log and debug your Ruby application using AppSignal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrate Your Ruby App with AppSignal
&lt;/h2&gt;

&lt;p&gt;To start debugging with AppSignal, you need to have an AppSignal account.&lt;/p&gt;

&lt;p&gt;Integrate your Ruby application with AppSignal by following the steps in the article &lt;a href="https://blog.appsignal.com/2021/12/01/ruby-on-rails-application-monitoring-with-appsignal.html"&gt;'Ruby on Rails Application Monitoring with AppSignal'&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Log Options
&lt;/h2&gt;

&lt;p&gt;Now that you have an application set up to send logs to AppSignal, let's look at the logging options for your Ruby application.&lt;/p&gt;

&lt;p&gt;AppSignal offers various log levels for your application according to your project's needs. In this section, we will explore the difference between each log level.&lt;/p&gt;

&lt;p&gt;At first glance, we might think these logs are related to the application logs shown in the 'Backtrace' section of AppSignal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RzO0y0N9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/backtrace.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RzO0y0N9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/backtrace.png" alt="Backtrace Section" width="800" height="828"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, changes to &lt;code&gt;log_level&lt;/code&gt; won't reflect the information displayed in the backtrace. It is important to understand that setting the &lt;code&gt;log_level&lt;/code&gt; value relates to AppSignal's communication logs with your application. It has nothing to do with application logs.&lt;/p&gt;

&lt;p&gt;This means that when we set the logging level in our application, we change the type of information that appears in the application logs about execution and integration with AppSignal.&lt;/p&gt;

&lt;p&gt;In most cases, you can just set the &lt;code&gt;log_level&lt;/code&gt; to error (unless you've had an issue with the AppSignal integration and need to send log information to AppSignal's Support team). The &lt;code&gt;log_level&lt;/code&gt; must be defined in &lt;code&gt;config/appsignal.yml&lt;/code&gt;, as in the example below:&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;# config/appsignal.yml&lt;/span&gt;

&lt;span class="ss"&gt;production:
  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;defaults&lt;/span&gt;
  &lt;span class="ss"&gt;log_level: &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch the application logs when we set &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;warning&lt;/code&gt;, or &lt;code&gt;info&lt;/code&gt; to &lt;code&gt;log_level&lt;/code&gt;. We will see pretty much the same information in the logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HKFqYCDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/error.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HKFqYCDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/error.png" alt="error as log_level" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, check out the logs when we set &lt;code&gt;log_level&lt;/code&gt; as &lt;code&gt;debug&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SUFU1BAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/debug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SUFU1BAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/debug.png" alt="debug as log_level" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, let's see what happens when we set &lt;code&gt;log_level&lt;/code&gt; as &lt;code&gt;trace&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aFwX-Quz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/trace.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aFwX-Quz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/trace.png" alt="trace as log_level" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ignore Your Ruby App's Predicted Errors in AppSignal
&lt;/h2&gt;

&lt;p&gt;You don't need to catch and keep all errors in logs. Some common errors can be expected in an application — we don't need to inflate our logs with 404 errors, for example. Now let's configure AppSignal to ignore errors that are irrelevant to trace.&lt;/p&gt;

&lt;p&gt;Ignoring an error is useful when a production bug has already been identified, but the fix is still in development. We already know about the problem's existence, so there's no need to keep filling the error monitoring tool or be notified about it. We can ignore the error's appearance until the patch deployment goes into production. This approach can be applied to all known bugs that have already been cataloged in the issues list.&lt;/p&gt;

&lt;p&gt;We can also ignore errors when we know that a service our application communicates with will be down for maintenance. This way, we don't flood the monitoring tool with errors regarding expected maintenance, alerting our monitoring team unnecessarily.&lt;/p&gt;

&lt;p&gt;AppSignal's gem provides three ways to handle and ignore predicted errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ignore_errors&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ignore_errors&lt;/code&gt; helps when you need to ignore all errors generated by a class error or when you don't know the exact error that could happen from there.&lt;/p&gt;

&lt;p&gt;Maybe your application needs to do many math calculations, and AppSignal doesn't need to track all related errors. &lt;code&gt;ignore_errors&lt;/code&gt; will reduce the errors list and only keep issues that need to be addressed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ignore_actions&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is useful if you know exactly which method will generate an error you don't need to trace — for example, a method that will be re-executed until it succeeds. You can also use &lt;code&gt;ignore_actions&lt;/code&gt; for queue processing when another monitoring tool handles logs specific to queue item failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ignore_namespace&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ignore_namespace&lt;/code&gt; is great if you have an application separated by domain and want to group errors. Maybe you have a specific module to treat payments or to process an order in the background. Grouping it in a namespace for jobs makes sense. Then you can ignore the exceptions that occur inside this namespace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure in Your Ruby App
&lt;/h3&gt;

&lt;p&gt;Include &lt;code&gt;ignore_errors&lt;/code&gt;, &lt;code&gt;ignore_actions&lt;/code&gt;, and &lt;code&gt;ignore_namespace&lt;/code&gt; in your &lt;code&gt;config/appsignal.yml&lt;/code&gt; file, with a list of classes to ignore when this error occurs in your application.&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;# config/appsignal.yml&lt;/span&gt;

&lt;span class="ss"&gt;production:
  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;defaults&lt;/span&gt;
  &lt;span class="ss"&gt;ignore_errors:
    &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;HTTPGatewayTimeout&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="no"&gt;NoMethodError&lt;/span&gt;
  &lt;span class="ss"&gt;ignore_actions:
    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="no"&gt;HomeController&lt;/span&gt;&lt;span class="c1"&gt;#index&lt;/span&gt;
  &lt;span class="ss"&gt;ignore_namespace:
    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging Exceptions in Ruby with AppSignal
&lt;/h2&gt;

&lt;p&gt;Now that we know how to ignore irrelevant errors, it's time to deal with the errors that matter. AppSignal provides functions to configure how an error is sent from your application to the AppSignal monitor. Let's learn about the &lt;code&gt;listen_for_error&lt;/code&gt; feature and extract valuable information from exceptions.&lt;/p&gt;

&lt;p&gt;Sometimes, we have a situation where an exception may or may not be thrown due to some parameters (if a job is not running or even if an external endpoint is unavailable). We still want to send detailed information to AppSignal, not just the exception itself. For this case, we'll create a custom exception and use it to send helpful information to the monitoring team.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is create a class for our custom exception. Make a new folder called &lt;code&gt;exceptions&lt;/code&gt; inside your application directory. Then create a new class called &lt;code&gt;CustomException&lt;/code&gt; inherited from &lt;code&gt;StandardError&lt;/code&gt;. You can define any information as the content of this exception. By default, an exception already has &lt;code&gt;msg&lt;/code&gt; as an attribute.&lt;/p&gt;

&lt;p&gt;In this example, you need to include an exception &lt;code&gt;name&lt;/code&gt; and the &lt;code&gt;content&lt;/code&gt; field to report all details about the exception. In the exception constructor, all attributes are set and the method to send to AppSignal is called.&lt;/p&gt;

&lt;p&gt;The block inside &lt;code&gt;Appsignal.listen_for_error&lt;/code&gt; is where the magic happens! The raise will send the exception content to AppSignal in hash format to facilitate the separation of the different contents.&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;# app/exceptions/custom_exception.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomException&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
    &lt;span class="vi"&gt;@msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
    &lt;span class="vi"&gt;@content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;

    &lt;span class="n"&gt;send_exception_to_appsignal&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_exception_to_appsignal&lt;/span&gt;
    &lt;span class="no"&gt;Appsignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen_for_error&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;exception_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;msg: &lt;/span&gt;&lt;span class="vi"&gt;@msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="vi"&gt;@content&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;exception_hash&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Now you can call this custom exception from anywhere, to use it in your application. For this example, we will include it in the controller inside the &lt;code&gt;Home#index&lt;/code&gt; method. We need a block to handle the exception, to avoid sending it to AppSignal. The &lt;code&gt;nil.object&lt;/code&gt; code will throw a &lt;code&gt;NoMethodError&lt;/code&gt; exception, but this exception is handled, and only &lt;code&gt;CustomException&lt;/code&gt; will be sent to AppSignal.&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;# app/controllers/home_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomeController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CustomException&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Customized Exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"A new exception occurred"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&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;All done! After starting your application and accessing &lt;a href="http://localhost:3000/home#index"&gt;http://localhost:3000/home#index&lt;/a&gt; in your browser, you will see a page with a &lt;code&gt;RuntimeError&lt;/code&gt; exception. In AppSignal, access the 'Errors &amp;gt; Issue list' to see the Customized Exception issue.&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="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Customized Exception"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:msg&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"A new exception occurred"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt;#&amp;lt;NoMethodError: undefined method `object' for nil:NilClass&amp;gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v9cF6GB4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/custom-exception.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v9cF6GB4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://blog.appsignal.com/images/blog/2022-09/custom-exception.png" alt="Custom Exception" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up and Next Steps
&lt;/h2&gt;

&lt;p&gt;AppSignal provides a well-documented gem to start truly monitoring your Ruby application. Why not test it? Send data from your local machine without deploying to see if the error configuration is how you want it.&lt;/p&gt;

&lt;p&gt;Many other features in AppSignal make it easier to debug Ruby applications, like &lt;a href="https://docs.appsignal.com/ruby/instrumentation/exception-handling.html"&gt;exception handling&lt;/a&gt;. &lt;a href="https://docs.appsignal.com/ruby/"&gt;Check AppSignal's Ruby documentation&lt;/a&gt; and choose the feature that makes the most sense in your project's context. Make your app easier to debug by decreasing the time your team needs to spend looking into the root cause of bugs in production.&lt;/p&gt;

&lt;p&gt;Happy debugging!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S. If you'd like to read Ruby Magic posts as soon as they get off the press, &lt;a href="https://blog.appsignal.com/ruby-magic"&gt;subscribe to our Ruby Magic newsletter and never miss a single post&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Deploy Your Ruby on Rails App Using Capistrano</title>
      <dc:creator>Brena Monteiro</dc:creator>
      <pubDate>Wed, 27 Jul 2022 11:46:24 +0000</pubDate>
      <link>https://dev.to/appsignal/deploy-your-ruby-on-rails-app-using-capistrano-1996</link>
      <guid>https://dev.to/appsignal/deploy-your-ruby-on-rails-app-using-capistrano-1996</guid>
      <description>&lt;p&gt;In this article, we will configure Capistrano in a Ruby on Rails application. We will then deploy the app to a cloud instance that runs Ubuntu as an operating system, independent of your hosting provider. You can use any cloud service, or even an on-premises server, to test or replicate the steps we'll take.&lt;/p&gt;

&lt;p&gt;Once we've deployed the app, we'll look briefly at how you can monitor your app's deployments using AppSignal.&lt;/p&gt;

&lt;p&gt;But first, you might ask: why should I use Capistrano in the first place?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Choose Capistrano for Your Ruby on Rails App?
&lt;/h2&gt;

&lt;p&gt;You might be wondering if it still makes sense to continue using Capistrano for deployment these days. We now have many tools and services available for deployments and continuous integration.&lt;/p&gt;

&lt;p&gt;But to answer that, we need to revisit the origin of Capistrano and its evolution to the present day. The first tag created in the Capistrano repository was in 2006. Its objective was to allow the execution of commands remotely via SSH in parallel on several machines, all using DSL. Since then, Capistrano has evolved, by adding several features to each version.&lt;/p&gt;

&lt;p&gt;Currently at version 3 after 16 years, Capistrano continues to be actively developed and is now known as a framework for building automated deployment scripts.&lt;/p&gt;

&lt;p&gt;So it's no longer just a tool to run commands on remote machines. In addition to &lt;a href="https://capistranorb.com/documentation/plugins" rel="noopener noreferrer"&gt;Capistrano's features&lt;/a&gt;, many &lt;a href="https://capistranorb.com/documentation/third-party-plugins" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; and other gems specifically run with Capistrano.&lt;/p&gt;

&lt;p&gt;Because of this and the fact that a large community still uses Capistrano, it remains a great tool for automated deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Capistrano to Your Ruby on Rails App
&lt;/h2&gt;

&lt;p&gt;First, you'll need to configure a Ruby on Rails application to integrate it with Capistrano. You can follow &lt;a href="https://capistranorb.com/documentation/getting-started/installation" rel="noopener noreferrer"&gt;Capistrano's documentation&lt;/a&gt;. However, it has more information than you'll need for the scope of this post. So for simplicity's sake, this article only includes the necessary steps and configuration that you will need.&lt;/p&gt;

&lt;p&gt;To start the configuration, add the Capistrano gem in the development section of your Gemfile:&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;group&lt;/span&gt; &lt;span class="ss"&gt;:development&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Deployment&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"capistrano"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 3.10"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"capistrano-rails"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need the capistrano-rails gem to run a migration on your database and handle the assets that we will see in the next sections.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;bundle install&lt;/code&gt; to add Capistrano to your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can install Capistrano:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;cap &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a file called &lt;code&gt;Capfile&lt;/code&gt; that imports and configures the required libraries. Furthermore, a file called &lt;code&gt;deploy.rb&lt;/code&gt; (created inside the &lt;code&gt;config&lt;/code&gt; folder) will contain all the configurations that should be included in a deployment with Capistrano.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; Capistrano creates a file to override the &lt;code&gt;deploy.rb&lt;/code&gt; configuration for both the staging and production environments, but that will not be covered in this article.&lt;/p&gt;

&lt;p&gt;With that, you're ready to start configuring and communicating between your Ruby on Rails application and the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Configuration with Capistrano for Your Rails App
&lt;/h2&gt;

&lt;p&gt;In this step, we'll add instructions to the Capistrano configuration file. The instructions will communicate to your server on where your app will be deployed. This is where we'll define access information and the security configuration.&lt;/p&gt;

&lt;p&gt;To ensure that your production environment runs the same version of Ruby as the version you use in development, use a Ruby version manager, such as &lt;em&gt;RVM&lt;/em&gt; or &lt;em&gt;rbenv&lt;/em&gt; (Capistrano supports both).&lt;/p&gt;

&lt;p&gt;In this article, we'll use RVM. Make sure you have RVM installed on your development machine and production server. Also, check if your version of Ruby is the same in your environments and project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding &lt;code&gt;capistrano-rvm&lt;/code&gt; Gem
&lt;/h3&gt;

&lt;p&gt;The Capistrano project provides a gem called &lt;em&gt;capistrano-gem&lt;/em&gt; that lets you easily configure RVM. To include it in your project, add it to your Gemfile within your development group, and run &lt;code&gt;bundle install&lt;/code&gt; again.&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="s2"&gt;"capistrano-rvm"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your Capfile with the capistrano-rvm import:&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;# Capfile&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/rvm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the deploy file, add a configuration to set the Ruby version and the path to RVM (especially if you used a different path to install RVM).&lt;/p&gt;

&lt;p&gt;If no version of Ruby is defined, Capistrano chooses the latest version that you have installed on the server where your application will be deployed.&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;# config/deploy.rb&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rvm_ruby_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ruby-2.6.3"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:default_env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;rvm_bin_path: &lt;/span&gt;&lt;span class="s2"&gt;"~/.rvm/bin"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/capistrano/rvm" rel="noopener noreferrer"&gt;Capistrano::RVM&lt;/a&gt; has other settings for RVM, but the ones shown here are what you'll need to get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up Your Server Configuration
&lt;/h3&gt;

&lt;p&gt;It is good practice to define a user for the deployment. Don't forget to follow these steps on your server before you start a deployment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the public key generated on your local machine to the &lt;code&gt;~/home/YOUR_USER/.ssh/authorized_keys&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Create a key and include the public key in the code repository. This gives you access to clone your project within the production server. If you are using GitHub, you can &lt;a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent" rel="noopener noreferrer"&gt;follow this documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Set permissions to write to the &lt;code&gt;/var/www/&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can configure Capistrano for any environment you need. You just need to create a new configuration file inside &lt;code&gt;config/deploy/&amp;lt;environment_name&amp;gt;.rb&lt;/code&gt;, then configure the IP or DNS, and username, to connect to your server.&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;# config/deploy/production.rb&lt;/span&gt;

&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="s2"&gt;"11.22.333.444"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user: &lt;/span&gt;&lt;span class="s2"&gt;"ubuntu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;roles: &lt;/span&gt;&lt;span class="sx"&gt;%w{app db web}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To complete the deployment setup, include information about your application, such as the application name and code repository URL. Any information which is the same for all environments must be added to &lt;code&gt;config/deploy.rb&lt;/code&gt;. Keep specific environment configurations in &lt;code&gt;config/deploy/&amp;lt;environment_name&amp;gt;.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="c1"&gt;# config/deploy.rb&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ruby_rails_app"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:repo_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"git@github.com:username/ruby_rails_app.git"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up &lt;code&gt;capistrano-secrets-yml&lt;/code&gt; Gem for Your Rails App
&lt;/h3&gt;

&lt;p&gt;You should also set up the &lt;a href="https://github.com/capistrano-plugins/capistrano-secrets-yml" rel="noopener noreferrer"&gt;capistrano-secrets-yml&lt;/a&gt; gem.&lt;/p&gt;

&lt;p&gt;Add the gem to your Gemfile and run the bundle to install:&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;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"capistrano-secrets-yml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import it into Capfile:&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;# Capfile&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"capistrano/secrets_yml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create &lt;code&gt;config/secret.yml&lt;/code&gt; in your application and include the secret key base as an environment variable. This variable will be created on your production server. Remember &lt;em&gt;not&lt;/em&gt; to commit this file to your repository.&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;# config/secrets.yml&lt;/span&gt;
&lt;span class="ss"&gt;production:
  secret_key_base: &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= ENV["SECRET_KEY_BASE"] %&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside your application folder in the terminal, run this command to generate the secret key base:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rails secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the generated key and use it to set your SECRET_KEY_BASE on the production server. Access your production server and export the SECRET_KEY_BASE variable in the final &lt;code&gt;~/.bashrc&lt;/code&gt; file, so it is always available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ~/.bashrc&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SECRET_KEY_BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_SECRET_KEY_BASE"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the source to make it instantly available in your environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, back on your machine, access the application folder in the terminal and run the Capistrano command below to create &lt;code&gt;config/secrets.yml&lt;/code&gt; on the production server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cap production setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All done! Now it's time to configure Capistrano to run a migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Capistrano to Perform a Database Migration
&lt;/h2&gt;

&lt;p&gt;Now it's time to configure Capistrano to run database-related commands.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;capistrano-rails&lt;/em&gt; gem already included in your Gemfile can be configured to perform a migration on each deployment. We just need to import it into Capfile:&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;# Capfile&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"capistrano/rails/migrations"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you want to run the seeds on deployment, you need to create a new task to run after the migration:&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;# config/deploy.rb&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Run seed"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:seed&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:all&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;within&lt;/span&gt; &lt;span class="n"&gt;current_path&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="ss"&gt;:bundle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:exec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rails'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'db:seed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'RAILS_ENV=production'&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;span class="n"&gt;after&lt;/span&gt; &lt;span class="ss"&gt;:migrating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:seed&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, your app is finally ready to be deployed!&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Deployment of Your Ruby on Rails App
&lt;/h2&gt;

&lt;p&gt;Let's see how to perform a deployment from our local machine by directly updating our server to the new version of our application.&lt;/p&gt;

&lt;p&gt;When you execute a deployment command, Capistrano will connect to your server. From there, Capistrano will try to clone the code from the repository defined in the configuration file (&lt;code&gt;config/deploy.rb&lt;/code&gt;). Then other tasks will be performed, following the deployment flow.&lt;/p&gt;

&lt;p&gt;Capistrano's &lt;code&gt;deploy:check&lt;/code&gt; command validates that the Git configuration is alright and that Capistrano has correct access to the directories that will be used in the deployment.&lt;/p&gt;

&lt;p&gt;To use it, pass the environment. In this case, we are using production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cap production deploy:check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is ok with the configuration, you can start your deployment to production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cap production deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition, you can check all available tasks in Capistrano with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cap &lt;span class="nt"&gt;--tasks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in our final step, let's integrate our Ruby on Rails application with AppSignal and start monitoring it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Integrate AppSignal with Capistrano and Your Rails App
&lt;/h2&gt;

&lt;p&gt;AppSignal is a monitoring tool, so you might wonder why it's included in this article. That is a valid question, as monitoring is not directly related to deployments.&lt;/p&gt;

&lt;p&gt;That said, AppSignal is a valuable tool when it comes to monitoring your Ruby on Rails application and keeping track of deployments in each environment. So let's see how we can set up AppSignal for your app.&lt;/p&gt;

&lt;p&gt;You will need an AppSignal account, which you can create on &lt;a href="https://appsignal.com/users/sign_up" rel="noopener noreferrer"&gt;AppSignal's sign-up page&lt;/a&gt;. Pick Ruby as your language and follow the steps to install AppSignal in your application.&lt;/p&gt;

&lt;p&gt;Once installed, a file will be created to configure AppSignal. What's important here is to define the &lt;em&gt;revision&lt;/em&gt; — information that will be checked after deployment to see if a new version of an application has been deployed. In this case, we will use the Git log as revision information to ensure that each new code deployment will notify AppSignal.&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;# config/appsignal.yml&lt;/span&gt;

&lt;span class="ss"&gt;production:
  &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;defaults&lt;/span&gt;
  &lt;span class="ss"&gt;active: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="ss"&gt;revision: &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;%= `git log --pretty=format:'%h' -n 1` %&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is also good practice to export AppSignal environment variables to your production server (especially the API key, so as not to keep it in the AppSignal configuration file).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;APPSIGNAL_PUSH_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;XXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can rerun the deployment. If everything is set up correctly, you will see a message like this at the end of the deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Notifying AppSignal of deploy with: revision: ee5e626fd31613ef068873f9cddb5f8c91538396, user: monteirobrena
AppSignal has been notified of this deploy!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will now be able to see your application in AppSignal! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2022-07%2Fapplications-list.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2022-07%2Fapplications-list.png" alt="Applications list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And information about any deployments:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2022-07%2Fdeployments-list.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.appsignal.com%2Fimages%2Fblog%2F2022-07%2Fdeployments-list.png" alt="Deployments list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.appsignal.com/application/markers/deploy-markers.html" rel="noopener noreferrer"&gt;Visit AppSignal's deployment documentation page&lt;/a&gt; to learn more about deployment integration and other features available for Ruby on Rails applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up and Next Steps
&lt;/h2&gt;

&lt;p&gt;In this post, we explored how to use Capistrano to deploy your Ruby on Rails app. We first added Capistrano to an app, then configured and deployed it, before finally setting up monitoring with AppSignal.&lt;/p&gt;

&lt;p&gt;If you'd like to explore further, you can configure Capistrano to run from an integration connected to your repository's pipeline. Tools like Bitbucket, GitHub, and GitLab provide settings to manage this process and can be used in conjunction with Capistrano.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S. If you'd like to read Ruby Magic posts as soon as they get off the press, &lt;a href="https://blog.appsignal.com/ruby-magic" rel="noopener noreferrer"&gt;subscribe to our Ruby Magic newsletter and never miss a single post&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

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