<?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: Renata Marques</title>
    <description>The latest articles on DEV Community by Renata Marques (@renatamarques97).</description>
    <link>https://dev.to/renatamarques97</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%2F312161%2F79b4aa75-38a3-4cf7-9d06-93571807c9dc.jpeg</url>
      <title>DEV Community: Renata Marques</title>
      <link>https://dev.to/renatamarques97</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renatamarques97"/>
    <language>en</language>
    <item>
      <title>Mastering Ruby: Sequel and ActiveRecord, an overview</title>
      <dc:creator>Renata Marques</dc:creator>
      <pubDate>Tue, 21 Nov 2023 13:54:12 +0000</pubDate>
      <link>https://dev.to/renatamarques97/mastering-ruby-sequel-and-activerecord-an-overview-1m9l</link>
      <guid>https://dev.to/renatamarques97/mastering-ruby-sequel-and-activerecord-an-overview-1m9l</guid>
      <description>&lt;p&gt;Sequel and ActiveRecord are object-relational mapping for ruby-based applications, they have similarities and disparities, and this article will guide you to choose which one best suits your needs.&lt;/p&gt;

&lt;p&gt;If you are not familiar with the term ORM, here is a short explanation: ORMs provide a set of tools and conventions for mapping database tables and rows to corresponding objects and their attributes in the application code. This simplifies database interactions, eliminates the need to write raw SQL queries (but you can if you want), and allows developers to work with data using familiar programming paradigms.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ActiveRecord?
&lt;/h2&gt;

&lt;p&gt;ActiveRecord is an Object-Relational Mapping (ORM) library that is an integral part of the Ruby on Rails framework. It provides an abstraction layer that allows you to interact with a database using Ruby objects and methods rather than writing raw SQL queries. ActiveRecord simplifies database interactions, data validation, and the handling of associations between different types of data.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can I use it?
&lt;/h3&gt;

&lt;p&gt;Here's how you can use ActiveRecord in a Ruby-based application, particularly within the context of Ruby on Rails:&lt;/p&gt;

&lt;p&gt;Setup and Configuration:&lt;br&gt;
In a Rails application, ActiveRecord is included by default. There's no need to install it separately.&lt;/p&gt;

&lt;p&gt;Configure your database connection in the &lt;code&gt;config/database.yml&lt;/code&gt; file. Specify the database adapter, host, database name, user, password, and other connection details.&lt;/p&gt;

&lt;p&gt;Creating Models:&lt;br&gt;
Create Ruby classes that inherit from &lt;code&gt;ActiveRecord::Base&lt;/code&gt;. Each model class typically corresponds to a database table.&lt;br&gt;
Define attributes as instance variables in the model class to represent table columns.&lt;br&gt;
Establish associations (e.g., &lt;code&gt;has_many&lt;/code&gt;, &lt;code&gt;belongs_to&lt;/code&gt;, &lt;code&gt;has_and_belongs_to_many&lt;/code&gt;) between model classes to define relationships in the database.&lt;/p&gt;

&lt;p&gt;Migrations:&lt;br&gt;
Use migrations to manage your database schema. Migrations allow you to create, modify, and delete database tables and columns.&lt;br&gt;
Migrations provide a version control-like system for your database structure, enabling you to keep track of changes over time.&lt;/p&gt;

&lt;p&gt;CRUD Operations:&lt;br&gt;
Create: Use the &lt;code&gt;create&lt;/code&gt; method on your model class to insert new records into the database.&lt;br&gt;
Read: Use methods like &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;where&lt;/code&gt;, and &lt;code&gt;all&lt;/code&gt; to retrieve records from the database.&lt;br&gt;
Update: Use the &lt;code&gt;update&lt;/code&gt; method or combination of &lt;code&gt;find&lt;/code&gt; and &lt;code&gt;save&lt;/code&gt; to modify existing records.&lt;br&gt;
Delete: Use the &lt;code&gt;destroy&lt;/code&gt; method to remove records from the database.&lt;/p&gt;

&lt;p&gt;Validation:&lt;br&gt;
Define validation rules using ActiveRecord's built-in validation methods. These ensure that the data entering the database meets specific criteria.&lt;br&gt;
Common validations include &lt;code&gt;presence&lt;/code&gt;, &lt;code&gt;length&lt;/code&gt;, &lt;code&gt;uniqueness&lt;/code&gt;, and more.&lt;/p&gt;

&lt;p&gt;Callbacks:&lt;br&gt;
Use callbacks to execute code at specific points in the lifecycle of a model instance. Examples include &lt;code&gt;before_save&lt;/code&gt;, &lt;code&gt;after_create&lt;/code&gt;, and &lt;code&gt;before_destroy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Associations:&lt;br&gt;
Leverage ActiveRecord's association methods to establish relationships between different model classes. This allows you to navigate and manipulate related data.&lt;/p&gt;

&lt;p&gt;Query Interface:&lt;br&gt;
Use ActiveRecord's query interface to construct and execute complex database queries using a fluent and Ruby-like syntax.&lt;br&gt;
Methods like &lt;code&gt;where&lt;/code&gt;, &lt;code&gt;joins&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, and &lt;code&gt;order&lt;/code&gt; can be combined to build intricate queries.&lt;/p&gt;

&lt;p&gt;Console and Rails Console:&lt;br&gt;
Use the Rails console (&lt;code&gt;rails console&lt;/code&gt;) to interact with your models and database in a live environment.&lt;br&gt;
Test your queries, create records, and perform various operations directly from the console.&lt;/p&gt;

&lt;p&gt;Error Handling:&lt;br&gt;
ActiveRecord provides exceptions and error messages when validation or database-related errors occur, helping you diagnose and troubleshoot issues.&lt;/p&gt;

&lt;p&gt;With AR you can also write custom SQL queries.&lt;/p&gt;

&lt;p&gt;You can check the documentation: &lt;a href="https://guides.rubyonrails.org/active_record_basics.html"&gt;https://guides.rubyonrails.org/active_record_basics.html&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Sequel?
&lt;/h2&gt;

&lt;p&gt;Sequel is a popular Object-Relational Mapping (ORM) library for Ruby that provides a simple and flexible way to interact with databases. It offers an alternative to ActiveRecord, the default ORM in Ruby on Rails. Sequel is known for its lightweight design, extensive feature set, and focus on providing a more SQL-centric approach.&lt;/p&gt;
&lt;h3&gt;
  
  
  How can I use it?
&lt;/h3&gt;

&lt;p&gt;Here's how you can use Sequel in your Ruby-based application:&lt;br&gt;
Installation: Add the Sequel gem to your Gemfile and run bundle install.&lt;/p&gt;

&lt;p&gt;Database Configuration: Configure your database connection in your application. Sequel supports a wide range of database systems, including PostgreSQL, MySQL, SQLite, and more. You'll need to specify the appropriate adapter, host, database name, user, password, and any other relevant connection options.&lt;/p&gt;

&lt;p&gt;Model Definitions: Define your models by creating Ruby classes that inherit from Sequel::Model. Each model class should represent a table in your database. Define associations, validations, and other model-specific configurations using Sequel's API.&lt;/p&gt;

&lt;p&gt;Queries: Use Sequel's query methods to interact with the database. Sequel provides a wide range of methods to build complex queries, including filtering, sorting, joining tables, and more.&lt;/p&gt;

&lt;p&gt;Creating Records: Instantiate your model classes to create new records in the database. Sequel provides an intuitive syntax to insert data.&lt;/p&gt;

&lt;p&gt;Retrieving Records: Use the model class's methods to retrieve records from the database. You can chain query methods to build complex queries.&lt;/p&gt;

&lt;p&gt;Updating and Deleting Records: Use Sequel's methods to update and delete records from the database.&lt;/p&gt;

&lt;p&gt;Associations: Define and work with associations between models using Sequel's association methods. These include one-to-one, one-to-many, and many-to-many associations.&lt;/p&gt;

&lt;p&gt;Migrations: Migrations are optional, you don’t have to use them. However, you can use Sequel's migration system to manage changes to your database schema over time.&lt;/p&gt;

&lt;p&gt;Hooks and callbacks: Implement hooks and callbacks to perform actions before or after certain events, such as saving records or validating data.&lt;/p&gt;

&lt;p&gt;Error Handling: Sequel provides error handling mechanisms to catch and manage exceptions that might occur during database operations.&lt;/p&gt;

&lt;p&gt;Custom SQL: While Sequel offers a wide range of high-level query methods, you can also write custom SQL queries when needed.&lt;/p&gt;

&lt;p&gt;You can check the syntax and more information about the Sequel ORM: &lt;a href="https://github.com/jeremyevans/sequel"&gt;https://github.com/jeremyevans/sequel&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  ActiveRecord vs. Sequel
&lt;/h2&gt;

&lt;p&gt;Choosing between Sequel and ActiveRecord depends on your project's requirements and preferences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are some scenarios where using Sequel might be more suitable than ActiveRecord&lt;/strong&gt;:&lt;br&gt;
Choosing between Sequel and ActiveRecord depends on your project's requirements and preferences. Here are some scenarios where using Sequel might be more suitable than ActiveRecord:&lt;/p&gt;

&lt;p&gt;Performance and Control: Sequel is known for its lightweight design and can offer better performance in certain scenarios. If you need more control over how queries are executed and want to optimize performance, Sequel's flexibility can be an advantage.&lt;/p&gt;

&lt;p&gt;Postgres Features: If you are using Postgres, Sequel employs the PG extended query protocol, making it significantly faster than ActiveRecord and reducing server-side resource usage. You can learn more about it (here)[&lt;a href="https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY"&gt;https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY&lt;/a&gt;]. Unlike Sequel, ActiveRecord doesn't fully leverage the potential of PostgreSQL.&lt;/p&gt;

&lt;p&gt;SQL-Centric Approach: Sequel has a powerful SQL DSL. If you're comfortable working with a more SQL-oriented approach to database interactions, Sequel's API aligns closely with SQL syntax. This can be advantageous when you need fine-grained control over your queries.&lt;br&gt;
Calling functions:&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;# Using Sequel&lt;/span&gt;

&lt;span class="c1"&gt;# defining the function on the database&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;
  CREATE FUNCTION add_numbers(a integer, b integer)
  RETURNS integer AS $$
  BEGIN
      RETURN a + b;
  END; $$
  LANGUAGE plpgsql;
&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling the function somewhere in the app.&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;Sequel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:add_numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:add_numbers=&amp;gt;3}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using ActiveRecord&lt;/span&gt;

&lt;span class="c1"&gt;# defining the function on the database&lt;/span&gt;
&lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;&lt;span class="sh"&gt;
  CREATE OR REPLACE FUNCTION add_numbers(a integer, b integer)
  RETURNS integer AS $$
  BEGIN
    RETURN a + b;
  END;
  $$ LANGUAGE plpgsql;
&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling the function somewhere in the app.&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;# Call the SQL function using a raw SQL query&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SELECT add_numbers(1, 2) AS add_numbers"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Access the result&lt;/span&gt;
&lt;span class="n"&gt;add_numbers_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"add_numbers"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows Sequel has better Ruby DSLs for calling functions, rather than having to go down and write raw SQL to call functions.&lt;/p&gt;

&lt;p&gt;Advanced Features: Sequel also provides advanced features like subqueries, window functions, and CTEs (Common Table Expressions).&lt;br&gt;
Subqueries example:&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;# Using Sequel&lt;/span&gt;

&lt;span class="c1"&gt;# Find users with the highest salary in each department&lt;/span&gt;
&lt;span class="n"&gt;subquery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:salaries&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;select_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:department_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select_append&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_salary&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:salaries&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subquery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:department_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:max_salary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Using ActiveRecord&lt;/span&gt;

&lt;span class="c1"&gt;# Find users with the highest salary in each department&lt;/span&gt;
&lt;span class="n"&gt;subquery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Salary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"department_id, MAX(salary) AS max_salary"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:department_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Salary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"INNER JOIN (&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;subquery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sql&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) max_salaries ON salaries.department_id = max_salaries.department_id AND salaries.salary = max_salaries.max_salary"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Window functions example:&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;# Sequel&lt;/span&gt;

&lt;span class="c1"&gt;# Calculate the average salary for each employee&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:salaries&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;select_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:employee_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select_append&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;over&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;partition: :employee_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;average_salary&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

&lt;span class="c1"&gt;# Calculate the average salary for each employee&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Salary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"employee_id, AVG(salary) OVER (PARTITION BY employee_id) AS average_salary"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CTEs example:&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;# Sequel&lt;/span&gt;

&lt;span class="c1"&gt;# Find employees with salaries above the department's average salary using a CTE&lt;/span&gt;
&lt;span class="n"&gt;cte&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:salaries&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;select_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:department_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select_append&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;average_salary&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:salaries&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:cte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;salary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:average_salary&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

&lt;span class="c1"&gt;# Find employees with salaries above the department's average salary using a subquery&lt;/span&gt;
&lt;span class="n"&gt;subquery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Salary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"department_id, AVG(salary) AS average_salary"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:department_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Salary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"INNER JOIN (&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;subquery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sql&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) avg_salaries ON salaries.department_id = avg_salaries.department_id"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"salaries.salary &amp;gt; avg_salaries.average_salary"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we can see how challenging is to achieve the same thing using ActiveRecord's query interface.&lt;/p&gt;

&lt;p&gt;Using Hanami or ROM: Hanami and ROM use Sequel under the hood, which is a powerful source and an alternative for Ruby on Rails.&lt;/p&gt;

&lt;p&gt;Methods at build time: Sequel provides a metaprogramming feature that allows you to define methods at the time you define your model class. These methods are shared among all instances of the class. It can lead to more efficient memory usage, as the methods are shared among instances. It can also make your code more organized, as methods are defined alongside the class.&lt;/p&gt;

&lt;p&gt;Complex Queries: When dealing with complex database queries, joins, subqueries, and advanced filtering, Sequel's expressive query-building methods can make it easier to construct intricate queries without sacrificing readability.&lt;/p&gt;

&lt;p&gt;Custom Data Types: If your application works with custom or non-standard data types that require more control over serialization and deserialization, Sequel's custom-type support can be beneficial.&lt;/p&gt;

&lt;p&gt;Legacy Databases: If your application interacts with a legacy database schema that doesn't adhere to Rails conventions, Sequel's ability to work with non-standard column and table names can be advantageous.&lt;/p&gt;

&lt;p&gt;Less Magic: Sequel emphasizes explicitness and minimizes "magic" behaviors. If you prefer to have a clearer understanding of what happens behind the scenes in your database interactions, Sequel might be a better fit.&lt;/p&gt;

&lt;p&gt;Lean Applications: For applications where you want to keep the overhead of the ORM to a minimum, Sequel's modular design and lack of excessive abstractions can be beneficial.&lt;/p&gt;

&lt;p&gt;Small Projects: Sequel's straightforward and focused API can be more suitable for smaller projects where you don't need all the features and complexity of ActiveRecord.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are some scenarios where using ActiveRecord might be more suitable than Sequel&lt;/strong&gt;:&lt;br&gt;
You're building a Ruby on Rails application: ActiveRecord is tightly integrated into the Ruby on Rails framework. If you're building a Rails application, using ActiveRecord provides a cohesive and familiar development experience.&lt;/p&gt;

&lt;p&gt;Convention Over Configuration: ActiveRecord follows Rails' convention over configuration principle. It comes with sensible defaults and a standardized approach to database interactions, which can speed up development.&lt;/p&gt;

&lt;p&gt;Fast Development: ActiveRecord's ease of use, automagic associations, and built-in query methods can help you quickly build applications with less boilerplate code.&lt;/p&gt;

&lt;p&gt;Community and Ecosystem: ActiveRecord is widely used, which means you'll find ample documentation, tutorials, and community support. If you're new to Ruby on Rails, the abundant resources can be a significant advantage.&lt;/p&gt;

&lt;p&gt;ORM Integration: If your project involves features closely integrated with Rails, such as form helpers, view scaffolding, and other framework-specific components, ActiveRecord's seamless integration is beneficial.&lt;/p&gt;

&lt;p&gt;It's important to note that ActiveRecord is the default ORM for Ruby on Rails, which provides a cohesive development experience for most Rails projects. ActiveRecord abstracts away much of the complexity of database interactions and integrates seamlessly with Rails conventions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disadvantages of both:&lt;/em&gt;&lt;br&gt;
Using views: By default, database views are treated as read-only when using ActiveRecord. This means that you can query data from views just like you would from tables, but you cannot perform direct write operations (insert, update, or delete) on views through ActiveRecord. Sequel, like ActiveRecord, treats views as read-only by default. Sequel models associated with views are typically used for querying data, not for performing direct write operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Deciding between Sequel and ActiveRecord depends on your specific needs, preferences, and the nature of your project. Ultimately, the decision between Sequel and ActiveRecord should be based on your familiarity with SQL, your project's requirements, your team's preferences, and the specific trade-offs you're willing to make. If you value control, performance, flexibility, and a more SQL-centric approach, Sequel could be a strong choice. If you prioritize convention, ease of use, and seamless integration with Rails, ActiveRecord might be a better fit.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>database</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Mastering Ruby: Common Performance Issues</title>
      <dc:creator>Renata Marques</dc:creator>
      <pubDate>Tue, 21 Nov 2023 13:48:39 +0000</pubDate>
      <link>https://dev.to/renatamarques97/mastering-ruby-common-performance-issues-55bn</link>
      <guid>https://dev.to/renatamarques97/mastering-ruby-common-performance-issues-55bn</guid>
      <description>&lt;p&gt;Why "Ruby is slow"? Well, some people say Ruby is slow based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ruby is an &lt;strong&gt;interpreted language,&lt;/strong&gt; and interpreted languages tend to be slower than compiled ones.&lt;/li&gt;
&lt;li&gt;Ruby uses &lt;strong&gt;garbage collection&lt;/strong&gt; (While Ruby uses garbage collection, it's worth noting that languages like C#, which also utilize garbage collection, demonstrate significantly superior performance compared to Ruby, Python, PHP, and similar languages.)&lt;/li&gt;
&lt;li&gt;Ruby &lt;strong&gt;method calls are slower than other programming languages&lt;/strong&gt; (although, because of duck typing, they are arguably faster than in strongly typed interpreted languages).&lt;/li&gt;
&lt;li&gt;Ruby &lt;a href="https://stackoverflow.com/questions/56087/does-ruby-have-real-multithreading" rel="noopener noreferrer"&gt;does not support **true multithreading&lt;/a&gt;** (with the exception of JRuby).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a list of problems that cause slowdowns in applications using Ruby and Ruby on Rails, the most popular Ruby-based web framework.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slowness&lt;/li&gt;
&lt;li&gt;Memory leaking&lt;/li&gt;
&lt;li&gt;N+1 queries&lt;/li&gt;
&lt;li&gt;Slow queries&lt;/li&gt;
&lt;li&gt;API payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Slowness&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Lack of Indexing: If your database tables are not properly indexed, queries can take longer to execute, especially for large datasets.&lt;/p&gt;

&lt;p&gt;Inefficient Algorithms: Poorly optimized algorithms can lead to slow execution times, especially for large datasets. Choosing the right data structures and algorithms can significantly improve performance.&lt;/p&gt;

&lt;p&gt;Ruby Version: Older versions of Ruby may lack performance optimizations and improvements available in newer versions.&lt;/p&gt;

&lt;p&gt;Framework and Library Choices: Some Ruby gems and libraries may not be optimized for performance, leading to slower execution times. Choose well-maintained and widely-used libraries when possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Solutions for slowness&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I strongly suggest measuring your application's performance before you change anything and then again after each change.&lt;/p&gt;

&lt;p&gt;Optimize Ruby code; use the built-in classes and methods when available rather than developing your own.&lt;/p&gt;

&lt;p&gt;Reduce nested if/else, loops, and hashes if possible; all of these operations are really expensive, and sometimes just refactoring your code can reduce the need.&lt;/p&gt;

&lt;p&gt;Don’t be afraid of using features of your database; for example, define stored procedures and functions, knowing that you can use them by communicating directly with the database through driver calls rather than ActiveRecord high-level methods. Implementing this technique can greatly enhance the performance of a data-bound Rails application.&lt;/p&gt;

&lt;p&gt;It involves storing content generated during the request-response cycle and reusing it when responding to similar requests, effectively boosting the application's speed. When you repeatedly request identical data throughout the processing of a single request and class-level caching isn't feasible due to data dependency on request parameters, consider caching the data to prevent redundant computations.&lt;/p&gt;

&lt;p&gt;Memoization involves caching the result of a method so subsequent calls to the method return the cached result, saving processing time. It is a type of caching focused on storing function return values. However, keep in mind that Memoization should be avoided in some cases, for example, when a function is going to change over time and your business logic relies on the latest value.&lt;/p&gt;

&lt;p&gt;You can learn more about memoization here: &lt;a href="https://blog.appsignal.com/2022/12/20/a-guide-to-memoization-in-ruby.html" rel="noopener noreferrer"&gt;A guide to memoization in Ruby.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Detecting and avoiding code smells&lt;/p&gt;

&lt;p&gt;Avoiding code duplication, unused variables, or method arguments, and detecting code smells with the use of a static code analyzer such as [&lt;a href="https://rubocop.org/" rel="noopener noreferrer"&gt;Rubocop&lt;/a&gt;](&lt;a href="https://github.com/rubocop/rubocop" rel="noopener noreferrer"&gt;https://github.com/rubocop/rubocop&lt;/a&gt;) and &lt;a href="https://rubygems.org/gems/rubycritic/versions/2.9.1" rel="noopener noreferrer"&gt;RubyCritic&lt;/a&gt;](&lt;a href="https://rubygems.org/gems/rubycritic/versions/2.9.1" rel="noopener noreferrer"&gt;https://rubygems.org/gems/rubycritic/versions/2.9.1&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Use HTML in your view templates and avoid excessive use of helpers. When utilizing form helpers, be mindful that they add an extra layer of processing.&lt;/p&gt;

&lt;p&gt;Keep your Ruby version updated.&lt;/p&gt;

&lt;p&gt;Manage your controllers wisely; filters can be costly, so avoid overusing them. Additionally, be mindful of using excessive instance variables that your view doesn't genuinely need; they can significantly impact performance.&lt;/p&gt;

&lt;p&gt;Avoid unnecessary gems. Only include gems that are genuinely required for your application. This reduces potential conflicts and keeps your application leaner.&lt;/p&gt;

&lt;p&gt;Keep your gems up to date to benefit from bug fixes, security patches, and new features. However, test thoroughly after updates to avoid compatibility issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;N+1 Query&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the context of database queries, an N+1 query is a situation where, when retrieving a list of records (N), each record triggers an additional query (+1) to the database for related data. This can lead to performance issues as the number of queries increases with the number of records retrieved, resulting in an inefficient use of resources and slower response times.&lt;/p&gt;

&lt;p&gt;Let's illustrate this with an example in Ruby using ActiveRecord, a popular Object-Relational Mapping (ORM) library:&lt;/p&gt;

&lt;p&gt;Suppose we have two models, &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Post&lt;/code&gt;, where each user has many posts, and the models are defined as follows:&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/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:posts&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/post.rb&lt;/span&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;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, let's say we want to retrieve all users and their posts:&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;# N+1 query example&lt;/span&gt;
&lt;span class="vi"&gt;@users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;

&lt;span class="vi"&gt;@users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"User: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Posts:"&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example, the &lt;code&gt;User.all&lt;/code&gt; query retrieves all users, but for each user, there is an additional query executed to fetch their associated posts. This leads to N+1 queries: one initial query to fetch all users and N additional queries (one per user) to fetch their posts.&lt;/p&gt;

&lt;p&gt;The best way to find n+1 queries is by reading your operation’s log. Then, you can see a record of every database query being made as part of each request and look for cases that might indicate an n+1 query that can be optimized.&lt;/p&gt;

&lt;p&gt;Generally, an n+1 query will look like numerous analogous queries being executed one after the other:&lt;/p&gt;

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

SELECT “posts”.&lt;span class="k"&gt;*&lt;/span&gt; FROM “posts” LIMIT 3

SELECT &lt;span class="s2"&gt;"users"&lt;/span&gt;.&lt;span class="k"&gt;*&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; WHERE &lt;span class="s2"&gt;"users"&lt;/span&gt;.&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 1 LIMIT 1

SELECT &lt;span class="s2"&gt;"users"&lt;/span&gt;.&lt;span class="k"&gt;*&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; WHERE &lt;span class="s2"&gt;"users"&lt;/span&gt;.&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 2 LIMIT 1

SELECT &lt;span class="s2"&gt;"users"&lt;/span&gt;.&lt;span class="k"&gt;*&lt;/span&gt; FROM &lt;span class="s2"&gt;"users"&lt;/span&gt; WHERE &lt;span class="s2"&gt;"users"&lt;/span&gt;.&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 3 LIMIT 1


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Possible solutions to address the N+1 query issue&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Eager loading is a technique where you fetch the associated records in a single query, reducing the number of database trips.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# Eager loading solution using `includes`&lt;/span&gt;
&lt;span class="vi"&gt;@users&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;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:posts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;

&lt;span class="vi"&gt;@users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"User: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Posts:"&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;ul&gt;
&lt;li&gt;Joins:
You can use a SQL &lt;code&gt;JOIN&lt;/code&gt; to retrieve both users and their posts in a single query.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# Join solution&lt;/span&gt;
&lt;span class="vi"&gt;@users&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;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:posts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users.*, posts.title as post_title'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="vi"&gt;@users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"User: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Post: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post_title&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;includes&lt;/code&gt; with nested associations:
If you have multiple levels of associations, you can use nested &lt;code&gt;includes&lt;/code&gt; to avoid multiple queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# Nested includes solution&lt;/span&gt;
&lt;span class="vi"&gt;@users&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;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;posts: :comments&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;

&lt;span class="vi"&gt;@users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"User: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Posts:"&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Title: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Comments:"&lt;/span&gt;
    &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;By using these solutions, you can avoid N+1 queries and improve the performance of your application when dealing with associated data.&lt;/p&gt;

&lt;p&gt;So, N+1 queries have been a consideration and concern in Ruby on Rails applications for many versions, and the best practices to avoid them have been part of the Rails development community's guidelines. Always ensure you are using the most recent version of Ruby on Rails to take advantage of the latest performance improvements and optimizations. The &lt;a href="https://rubygems.org/gems/bullet/versions/6.1.0" rel="noopener noreferrer"&gt;Bullet&lt;/a&gt; or &lt;a href="https://rubygems.org/gems/prosopite/versions/1.0.8" rel="noopener noreferrer"&gt;Prosopite&lt;/a&gt; gems can give a hand here by telling when to use eager loading and when not, and by adding a counter cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Memory Leaks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ruby's garbage collector should automatically clean up unused objects, but memory leaks can occur if objects are not properly deallocated. Frequent garbage collection can lead to slower execution times.&lt;/p&gt;

&lt;p&gt;Here you can learn more &lt;a href="[https://blog.appsignal.com/2022/07/27/how-to-track-down-memory-leaks-in-ruby.html](https://blog.appsignal.com/2022/07/27/how-to-track-down-memory-leaks-in-ruby.html)"&gt;how to track memory leaks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Memory leaks can be very unproductive and difficult to fix, and you will probably spend more time trying to fix them than actually building code. The best way to get rid of them is to avoid them at the beginning. That doesn’t mean you need premature optimization; just keeping your code clean should be enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Optimizing Memory Usage and Preventing Memory Leaks&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Ruby Garbage Collector (GC) module serves as an interface to Ruby's mark and sweep garbage collection mechanism. Runtime garbage collection significantly influences memory management and recycling.&lt;/p&gt;

&lt;p&gt;Although the GC operates automatically in the background as needed, the GC module allows you to manually invoke the GC when necessary and gain insights into the progress of garbage collection cycles. This module offers adjustable parameters that can help moderate performance.&lt;/p&gt;

&lt;p&gt;Several frequently used methods within this module include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;start/garbage_collect: This method initiates a manual garbage collection cycle.&lt;/li&gt;
&lt;li&gt;enable/disable: These methods activate or deactivate automatic garbage collection cycles. They return a boolean value reflecting the success of the operation.&lt;/li&gt;
&lt;li&gt;stat: This method supplies a list of keys and values that describe GC module performance. We will delve into these metrics in detail in the following section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To manually invoke the Garbage Collector, execute &lt;strong&gt;&lt;code&gt;GC.&amp;lt;method&amp;gt;&lt;/code&gt;&lt;/strong&gt; in your IRB or Rails console. For a deeper understanding of GC tuning, &lt;a href="[https://blog.appsignal.com/2021/11/17/practical-garbage-collection-tuning-in-ruby.html](https://blog.appsignal.com/2021/11/17/practical-garbage-collection-tuning-in-ruby.html)"&gt;take a look at this article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Alternative solutions for solving memory leaks&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Memory Profiler gem is an effective way of tracking the memory usage of ruby code.&lt;/p&gt;

&lt;p&gt;If you have memory leaks despite handling memory correctly, the memory allocator methods may be the culprit. Ruby typically utilizes malloc calls for memory allocation, freeing, and reallocation, as mentioned earlier. An alternative implementation of these methods is jemalloc, developed by Jason Evans. Jemalloc proves to be more efficient in memory management compared to other allocators, mainly due to its focus on fragmentation avoidance, heap profiling, and comprehensive monitoring and tuning hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Slow queries&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In addition to the techniques that were already mentioned earlier in this article, there are other optimizations that can be done to solve slow queries.&lt;/p&gt;

&lt;p&gt;Batch Processing: If you have a large dataset, consider breaking your queries into smaller batches to reduce the load on the database.&lt;/p&gt;

&lt;p&gt;Use Database Transactions: Wrap multiple database operations in a transaction to ensure atomicity and reduce the number of commits.&lt;/p&gt;

&lt;p&gt;Database Connection Pooling: Use connection pooling to efficiently manage database connections and reduce the overhead of establishing connections for each query.&lt;/p&gt;

&lt;p&gt;Monitor and Profile: Regularly monitor your application's database performance and profile your queries to identify slow or inefficient queries. Use tools like Rails' built-in profiler (&lt;strong&gt;&lt;code&gt;ruby-prof&lt;/code&gt;&lt;/strong&gt;) or database-specific profiling tools.&lt;/p&gt;

&lt;p&gt;Upgrade Database Versions: If you are using a relational database, ensure you are running the latest version with performance improvements and optimizations.&lt;/p&gt;

&lt;p&gt;Remember that the effectiveness of these techniques may vary depending on the specific database system you are using (e.g., PostgreSQL, MySQL, SQLite, etc.) and the nature of your data and queries. Regularly test and benchmark your application's performance to ensure you're making the most significant improvements to your queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;API payloads&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If your application relies on external services or APIs, slow responses from those services can impact your application's performance.&lt;/p&gt;

&lt;p&gt;Handling large amounts of data can slow down the application. Make sure to use pagination or limit the data retrieval to what is necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How to make API payloads faster&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use Compression: Compress the payload using techniques like gzip or Brotli. This reduces the data size and speeds up transmission.&lt;/p&gt;

&lt;p&gt;Limit Response Size: Only include essential data in the response. Avoid sending unnecessary fields to reduce the payload size.&lt;/p&gt;

&lt;p&gt;Use Pagination: Implement pagination for large datasets. This way, clients can request only a subset of the data they need.&lt;/p&gt;

&lt;p&gt;Minimize Nested Objects: Try to flatten the JSON structure by avoiding deeply nested objects. This reduces parsing overhead on the client side.&lt;/p&gt;

&lt;p&gt;Enable HTTP/2: If possible, use HTTP/2, which allows multiple concurrent requests over a single connection, reducing latency.&lt;/p&gt;

&lt;p&gt;Load Balancing: Implement load balancing to distribute API requests across multiple servers, preventing bottlenecks and ensuring optimal performance.&lt;/p&gt;

&lt;p&gt;Monitor and Optimize: Continuously monitor your API's performance and usage patterns. Optimize and fine-tune as needed to accommodate changes in traffic.&lt;/p&gt;

&lt;p&gt;By following these strategies, you can significantly improve the speed and efficiency of your API payloads, resulting in a better user experience and reduced server load.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Using AppSignal to track issues&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;AppSignal is a performance-monitoring and error-tracking tool. It helps developers identify and solve performance issues, track errors, and gain insights into the health and performance of their Ruby applications.&lt;/p&gt;

&lt;p&gt;To use AppSignal to monitor and solve performance issues in a Ruby application, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sign Up and Install AppSignal:&lt;/strong&gt; First, sign up for an AppSignal account. Install the AppSignal gem in your Ruby application by adding it to your Gemfile and running &lt;code&gt;bundle install&lt;/code&gt;. For more information, &lt;a href="https://github.com/appsignal/appsignal-ruby" rel="noopener noreferrer"&gt;check the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure AppSignal:&lt;/strong&gt; Set up the configuration for AppSignal in your application. This usually involves providing your AppSignal API key and specifying any custom settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instrumentation:&lt;/strong&gt; AppSignal automatically instruments common Ruby frameworks and libraries to collect performance data. Additionally, you can add custom instrumentation to specific parts of your code to gain deeper insights into their performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoring and Error Tracking:&lt;/strong&gt; With AppSignal installed and configured, it will start monitoring your application in real time. It will collect performance data, such as response times, database queries, and HTTP calls, and track errors and exceptions.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7b0rkel9r3d7z6ul2bbl.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7b0rkel9r3d7z6ul2bbl.png" alt="Errors section on Appsignal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Dashboard:&lt;/strong&gt; Use the AppSignal web dashboard to visualize your application's performance metrics and error occurrences. The dashboard provides an overview of your application's health and allows you to dig into specific issues.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxjgm42bpjwoymmpa3ec.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxjgm42bpjwoymmpa3ec.png" alt="Web Dashboard on Appsignal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alerts and Notifications:&lt;/strong&gt; Configure alerts and notifications in AppSignal to be informed of critical performance issues or errors immediately. AppSignal can send notifications via email, Slack, or other communication channels.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspudlazo6nj22ojdo6a9.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspudlazo6nj22ojdo6a9.png" alt="Alerts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Profiling:&lt;/strong&gt; AppSignal also offers performance profiling, allowing you to analyze the performance of individual requests and find bottlenecks in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrations:&lt;/strong&gt; AppSignal integrates with popular tools like GitHub, Slack, and PagerDuty, making it easier to collaborate with your team and respond to issues promptly.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy7tqfo4rsnbtawhr781.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy7tqfo4rsnbtawhr781.png" alt="Integrations section on Appsignal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resolve Issues:&lt;/strong&gt; Use the data and insights provided by AppSignal to identify and resolve performance issues in your Ruby application. Optimize slow database queries, improve memory usage, and address other bottlenecks. &lt;a href="[https://blog.appsignal.com/2022/09/21/debugging-in-ruby-with-appsignal.html?utm_source=ruby-weekly-sponsored&amp;amp;utm_medium=email&amp;amp;utm_campaign=2022-09-21](https://blog.appsignal.com/2022/09/21/debugging-in-ruby-with-appsignal.html?utm_source=ruby-weekly-sponsored&amp;amp;utm_medium=email&amp;amp;utm_campaign=2022-09-21)"&gt;You can see more here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous Monitoring:&lt;/strong&gt; Keep AppSignal running in your production environment to continuously monitor your application's performance and detect issues as they arise.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3p4bnsueiekwp9d4lx88.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3p4bnsueiekwp9d4lx88.png" alt="Monitoring section on Appsignal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By leveraging AppSignal's monitoring capabilities, you can gain a deeper understanding of your Ruby application's performance, identify potential problem areas, and proactively resolve performance issues before they impact your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;People say ruby is slow because it &lt;em&gt;is&lt;/em&gt; slow based on measured comparisons to other languages. Bear in mind, though, that "slow" is relative. Often, Ruby and other "slow" languages are fast enough.&lt;/p&gt;

&lt;p&gt;But with the tuning performance advice, you can learn how to turn Ruby really fast, even compared to other compiled languages.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>performance</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>JIT Compilers for Ruby and Rails: An Overview</title>
      <dc:creator>Renata Marques</dc:creator>
      <pubDate>Wed, 14 Sep 2022 14:29:24 +0000</pubDate>
      <link>https://dev.to/appsignal/jit-compilers-for-ruby-and-rails-an-overview-42ib</link>
      <guid>https://dev.to/appsignal/jit-compilers-for-ruby-and-rails-an-overview-42ib</guid>
      <description>&lt;p&gt;A program is compiled at runtime using a different method from pre-execution compilation. This process is known as just-in-time compilation or dynamic translation.&lt;/p&gt;

&lt;p&gt;In this post, we'll look at why JIT compilation can be a good choice for your Ruby on Rails app, before looking at some of the options available (YJIT, MJIT, and TenderJIT) and how to install them.&lt;/p&gt;

&lt;p&gt;But first: how does JIT compilation work?&lt;/p&gt;

&lt;h2&gt;
  
  
  How a JIT Compiler Works
&lt;/h2&gt;

&lt;p&gt;Just-in-time compilation is a method of running computer code that requires compilation while running a program.&lt;/p&gt;

&lt;p&gt;This could entail translating the source code, but it's most frequently done by converting the bytecode to machine code, which is then run directly.&lt;/p&gt;

&lt;p&gt;The code being executed is often continuously analyzed by a system using a JIT compiler. This identifies sections of code where the benefit of compilation or recompilation (in terms of speed) outweighs the cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of JIT Compilation for Ruby
&lt;/h2&gt;

&lt;p&gt;JIT compilation combines some of the benefits (and shortcomings) of the two conventional methods for converting programs into machine code: interpretation and ahead-of-time compilation (AOT).&lt;/p&gt;

&lt;p&gt;Roughly speaking, it combines the flexibility of interpretation with the speed of generated code, and the additional overhead of compiling and linking (not just interpreting).&lt;/p&gt;

&lt;p&gt;JIT compilation is a type of dynamic compilation that enables adaptive optimization techniques, including dynamic recompilation and speed-ups tailored to certain microarchitectures. Due to a runtime system's ability to handle late-bound data types and impose security guarantees, dynamic programming languages like Ruby are particularly well-suited for interpretation and JIT compilation.&lt;/p&gt;

&lt;p&gt;An optimizing compiler like GCC can more efficiently optimize instructions — a significant advantage of adopting a register-oriented architecture. Compilers operate on intermediate representation with register-based architecture.&lt;/p&gt;

&lt;p&gt;Once your instructions reach an intermediate representation during compilation, GCC does additional passes to speed up the CPU's execution of your instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  JIT Compilers for Ruby: YJIT, MJIT, and TenderJIT
&lt;/h2&gt;

&lt;p&gt;Now let's explore the different JIT compilers available for Ruby — YJIT, MJIT, and TenderJIT — and how you can set them up.&lt;/p&gt;

&lt;h2&gt;
  
  
  MJIT (Method-based Just-in-time Compiler) for Ruby
&lt;/h2&gt;

&lt;p&gt;Vladimir Makarov implemented MJIT, and it was the first compiler methodology implemented in Ruby based on the C language. It works with Ruby 2.6, uses YARV instructions, and compiles instructions often used in binary code.&lt;/p&gt;

&lt;p&gt;For programs that are not input/output-bound, MJIT enhances performance.&lt;/p&gt;

&lt;p&gt;YJIT is better than this original C-based compiler in terms of performance. Ruby 3's JIT is the quickest JIT that MRI has ever had, made possible by the excellent work of MJIT.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use MJIT
&lt;/h3&gt;

&lt;p&gt;To use MJIT, you can enable the JIT in Ruby 2.6 and with the &lt;code&gt;--jit&lt;/code&gt; option.&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;ruby&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;jit&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you skip this part, MJIT will show an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clang: error: cannot specify &lt;span class="nt"&gt;-o&lt;/span&gt; when generating multiple output files
MJIT warning: Making precompiled header failed on compilation. Stopping MJIT worker...
MJIT warning: failed to remove &lt;span class="s2"&gt;"/var/folders/3d/fk_588wd4g12syc56pjqybjc0000gn/T//_ruby_mjit_hp25992u0.h.gch"&lt;/span&gt;: No such file or directory
Successful MJIT finish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A collection of JIT-specific settings included in Ruby 2.6 helps us understand how it functions. Run &lt;code&gt;ruby --help&lt;/code&gt; to view these options.&lt;/p&gt;

&lt;p&gt;In short, MJIT executes in a different thread and is asynchronous. It will begin just-in-time compilation following the first five runs of a calculation.&lt;/p&gt;

&lt;h2&gt;
  
  
  YJIT for Ruby on Rails
&lt;/h2&gt;

&lt;p&gt;A recent JIT compiler called YJIT was released with Ruby 3.1. It promises a lot of improvements and better performance. Still a work-in-progress project designed by Shopify with experimental results, it must be used with caution, especially on larger applications.&lt;/p&gt;

&lt;p&gt;With that in mind, YJIT enhances the performance of Ruby on Rails applications. The majority of real-world software benefits from the fast warm-up and performance enhancements provided by the YJIT basic block versioning JIT compiler.&lt;/p&gt;

&lt;p&gt;A JIT compiler will be gradually built into CRuby as part of the YJIT project, eventually replacing the interpreter for most of the code execution.&lt;/p&gt;

&lt;p&gt;Official benchmarks — see &lt;a href="https://shopify.engineering/yjit-just-in-time-compiler-cruby"&gt;'YJIT: Building a New JIT Compiler for CRuby'&lt;/a&gt; — show that YJIT improved performance over the default CRuby interpreter by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;20% on railsbench&lt;/li&gt;
&lt;li&gt;39% on liquid template rendering&lt;/li&gt;
&lt;li&gt;37% on activerecord&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only about 79% of instructions in railsbench are executed by YJIT, and the rest run in the default interpreter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://shopify.engineering/yjit-just-in-time-compiler-cruby"&gt;Source: YJIT: Building a New JIT Compiler for CRuby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that a lot still needs to be done to improve YJIT's current results.&lt;/p&gt;

&lt;p&gt;Even so, YJIT performs at least as well as the interpreter on every benchmark, even on the hardest ones, and reaches near-peak performance after just one iteration of every benchmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use YJIT
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: YJIT is currently limited to macOS and Linux on x86-64 platforms. Also, as mentioned, YJIT is not recommended for large applications (yet).&lt;/p&gt;

&lt;p&gt;YJIT is disabled by default. If you want to enable it, first specify the &lt;code&gt;--yjit&lt;/code&gt; command-line option.&lt;/p&gt;

&lt;p&gt;You need to check if it is installed, so run &lt;code&gt;ruby --enable-yjit -v&lt;/code&gt;. If &lt;code&gt;warning: unknown argument for --enable:&lt;/code&gt;yjit'` shows up, you have to install it.&lt;/p&gt;

&lt;p&gt;Then open &lt;code&gt;irb&lt;/code&gt; and set &lt;code&gt;RUBY_YJIT_ENABLE=1&lt;/code&gt;. You can exit and now, you're ready to use YJIT. The command &lt;code&gt;ruby --enable-yjit -v&lt;/code&gt; must return something like &lt;code&gt;ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin21]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TenderJIT
&lt;/h2&gt;

&lt;p&gt;With a design largely based off YJIT, TenderJIT is an experimental JIT compiler for Ruby. What's different about TenderJIT is that it's written in pure Ruby.&lt;/p&gt;

&lt;p&gt;This is a demo project and the aim is to ship it as a gem. In the meantime, you can experiment with it, but bear in mind it's still a work in progress. Ruby 3.0.2 or later is required for TenderJIT.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use TenderJIT
&lt;/h3&gt;

&lt;p&gt;TenderJIT does not currently do method compilation automatically. To compile a method, you must manually configure TenderJIT.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tenderlove/tenderjit"&gt;Clone the repository&lt;/a&gt; and run the following commands:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ bundle install&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ bundle exec rake test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You must set it manually on your code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require "tenderjit"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;def your_method&lt;/code&gt;&lt;br&gt;
  &lt;code&gt;...&lt;/code&gt;&lt;br&gt;
&lt;code&gt;end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jit = TenderJIT.new&lt;/code&gt;&lt;br&gt;
&lt;code&gt;jit.compile(method(:your_method))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Each YARV instruction in the target method is read by TenderJIT, which then transforms it into machine code.&lt;/p&gt;

&lt;p&gt;For more examples with TenderJIT, check one of these videos:&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=FCjwSOlHqbY&amp;amp;ab_channel=hexdevs"&gt;A JIT compiler for Ruby with Aaron Patterson&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=mPtouOS0gxE&amp;amp;ab_channel=Tenderlove%27sCoolStuff"&gt;Hacking on TenderJIT!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In this post, we've taken a quick look at three JIT compilers for Ruby — MJIT, YJIT, and TenderJIT — and how to set them up. Each of the options is experimental and comes with its own limitations.&lt;/p&gt;

&lt;p&gt;However, YJIT is the most mature at the moment, and it has the biggest potential to grow and scale. It demonstrates better performance over the other Ruby JITs, was developed with Ruby 3.1.0, and is quickly becoming an important part of CRuby.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://hokstad.com/compiler"&gt;Check out this post if you want to build your own compiler for Ruby&lt;/a&gt;.&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>
      <category>rails</category>
    </item>
    <item>
      <title>Mastering Ruby: Understanding Blocks, Procs, and Lambdas</title>
      <dc:creator>Renata Marques</dc:creator>
      <pubDate>Mon, 13 Jul 2020 01:34:27 +0000</pubDate>
      <link>https://dev.to/renatamarques97/understanding-blocks-procs-and-lambdas-in-ruby-2j38</link>
      <guid>https://dev.to/renatamarques97/understanding-blocks-procs-and-lambdas-in-ruby-2j38</guid>
      <description>&lt;p&gt;First, let's do a little introduction.&lt;/p&gt;

&lt;p&gt;Ruby blocks are anonymous functions that can be passed into methods, a way of grouping statements, are passed to methods that yield them within the &lt;code&gt;do&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; keywords, and they can have multiple arguments.&lt;/p&gt;

&lt;p&gt;A Proc object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another Proc, and can be called.&lt;/p&gt;

&lt;p&gt;Lambdas are anonymous functions, objects of the class Proc, they are useful in most of the situations where you would use a proc.&lt;/p&gt;

&lt;p&gt;So, procs are blocks, and lambdas are procs, that's because all of them are closures, and they have similar characteristics thanks for this. What is a closure in Ruby? A closure is basically a function that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can be treated as a variable, i.e. assigned to another variable, passed as a method argument, etc.&lt;/li&gt;
&lt;li&gt;Remembers the values of all the variables that were in scope when the function was defined and is able to access these variables even if it is executed in a different scope.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, what really sets them apart?&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between Block, Proc, and Lambda?
&lt;/h3&gt;

&lt;p&gt;First, Proc and lambda are objects but blocks are not.&lt;/p&gt;

&lt;p&gt;Second, a lambda checks the number of arguments passed to it, while a proc does not.&lt;br&gt;
This means that lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.&lt;/p&gt;

&lt;p&gt;Block uses the keyword yield, yield is a Ruby keyword that calls a block when you use it, the code inside the block will run and do its work.&lt;/p&gt;

&lt;p&gt;Like in the example below, they all are Ruby blocks:&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;print_message&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;print_message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Block message"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;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;Third,&lt;br&gt;
when a lambda returns, it passes control back to the calling method,&lt;br&gt;
when a proc returns, it does immediately, without going back to the calling method.&lt;/p&gt;

&lt;p&gt;Like 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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;best_movie_proc&lt;/span&gt;
  &lt;span class="n"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Proc&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="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Harry Potter!"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
  &lt;span class="s2"&gt;"Lord of the rings!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;best_movie_proc&lt;/span&gt; &lt;span class="c1"&gt;# prints "Harry Potter!"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;best_movie_lambda&lt;/span&gt;
  &lt;span class="n"&gt;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"Harry Potter!"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
  &lt;span class="s2"&gt;"Lord of the rings!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;best_movie_lambda&lt;/span&gt; &lt;span class="c1"&gt;# prints "Lord of the rings!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how the proc says "Harry Potter!", this is because it returns immediately, without going back to the best_movie_proc method.&lt;/p&gt;

&lt;p&gt;Our lambda, however, goes back into the method after being called, so the method returns the last code it evaluates: "Lord of the rings!"&lt;/p&gt;

&lt;h3&gt;
  
  
  Calls
&lt;/h3&gt;

&lt;p&gt;Block call&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;method&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;block_given?&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Block message"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the given example, we have a block passed with yield keyword.&lt;/p&gt;

&lt;p&gt;Proc call&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;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="c1"&gt;# or proc.()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;proc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Proc message"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_proc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In procs, we have two different syntaxes, with &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;.()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lambda call&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;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="c1"&gt;# or lambda.()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_lambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Lambda message"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_lambda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because lambdas are procs, they also have the same call syntax, but they are different to create.&lt;/p&gt;

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

&lt;p&gt;I hope it has become clearer for you to harness the power of Ruby closures.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>blocks</category>
      <category>procs</category>
      <category>lambdas</category>
    </item>
    <item>
      <title>Design Patterns with Ruby on Rails part 2: Query Object</title>
      <dc:creator>Renata Marques</dc:creator>
      <pubDate>Mon, 22 Jun 2020 01:04:44 +0000</pubDate>
      <link>https://dev.to/renatamarques97/design-patterns-with-ruby-on-rails-part-2-query-object-1h65</link>
      <guid>https://dev.to/renatamarques97/design-patterns-with-ruby-on-rails-part-2-query-object-1h65</guid>
      <description>&lt;p&gt;This post is the second part of a series of posts about design patterns with Ruby on Rails.&lt;br&gt;
See other parts here:&lt;br&gt;
&lt;a href="https://dev.to/renatamarques97/design-patterns-with-ruby-on-rails-part-1-introduction-and-policy-object-1c37"&gt;Part 1&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Query Object
&lt;/h4&gt;

&lt;p&gt;The query object is a pattern that helps in decomposing your fat ActiveRecord models and keeping your code slim and readable by extracting complex SQL queries or scopes into the separated classes that are easy to reuse and test.&lt;/p&gt;
&lt;h4&gt;
  
  
  Naming Convention
&lt;/h4&gt;

&lt;p&gt;Usually located in &lt;code&gt;app/queries&lt;/code&gt; directory, and of course, can be organized into multiple namespaces.&lt;br&gt;
Typical file name has &lt;code&gt;_query&lt;/code&gt; suffix, class name has &lt;code&gt;Query&lt;/code&gt; suffix.&lt;br&gt;
e.g.:&lt;br&gt;
&lt;code&gt;Posts::ActivePostsQuery&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;module&lt;/span&gt; &lt;span class="nn"&gt;Posts&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActivePostsQuery&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
      &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;deleted_at: &lt;/span&gt;&lt;span class="kp"&gt;nil&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;Class methods are more practical and easier to stub.&lt;/p&gt;

&lt;p&gt;There is a way to divide this query into pieces and become even more reusable? Yes, chaining methods.&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;PostsQuery&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;posts&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;active&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;active: &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;pending: &lt;/span&gt;&lt;span class="kp"&gt;false&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;def&lt;/span&gt; &lt;span class="nf"&gt;pending&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;pending: &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;active: &lt;/span&gt;&lt;span class="kp"&gt;false&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;def&lt;/span&gt; &lt;span class="nf"&gt;deleted&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_deleted&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 way:&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;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PostsQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pending&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Query objects and model scopes
&lt;/h4&gt;

&lt;p&gt;I have the following scope defined in Post 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;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;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;section: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'web'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mobile'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;deleted_at: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&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;and you want to extract this query and keep this behavior with &lt;code&gt;Post.active&lt;/code&gt;, how can you do this?&lt;/p&gt;

&lt;p&gt;The solution may seen obvious:&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;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active&lt;/span&gt;
    &lt;span class="no"&gt;ActivePostsQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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;but it adds more code and it is no longer visible in the scope definition.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using a scope with query objects
&lt;/h4&gt;

&lt;p&gt;Don't forget that your query object has to return a relation.&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;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActivePostsQuery&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's design our query object 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;class&lt;/span&gt; &lt;span class="nc"&gt;ActivePostsQuery&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="n"&gt;delegate&lt;/span&gt; &lt;span class="ss"&gt;:call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: :new&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;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@relation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relation&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;call&lt;/span&gt;
    &lt;span class="vi"&gt;@relation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;deleted_at: &lt;/span&gt;&lt;span class="kp"&gt;nil&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;Now the query still available via &lt;code&gt;Post.active&lt;/code&gt; scope.&lt;/p&gt;

&lt;h4&gt;
  
  
  Refactoring
&lt;/h4&gt;

&lt;p&gt;Let's take a look at how to use query objects in practice when refactoring larger queries.&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;PostsController&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="vi"&gt;@posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;active: &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;deleted_at: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:authors&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;emails: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;active: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When is time to write tests for this action it won't be possible without consulting the database.&lt;br&gt;
It gets easier after extracting this query to a separated 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;class&lt;/span&gt; &lt;span class="nc"&gt;ActivePostsWithAuthorQuery&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:relation&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&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;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@relation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relation&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;call&lt;/span&gt;
    &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_author&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;active&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;active: &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;deleted_at: &lt;/span&gt;&lt;span class="kp"&gt;nil&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;def&lt;/span&gt; &lt;span class="nf"&gt;with_author&lt;/span&gt;
    &lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:authors&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;emails: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;active: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the controller can be now updated:&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;PostsController&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="vi"&gt;@posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActivePostsWithAuthorQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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;h4&gt;
  
  
  Testing
&lt;/h4&gt;

&lt;p&gt;The queries it's not a controller concern anymore, it simplifies your test, now you can simply call &lt;code&gt;allow(ActivePostsWithAuthorQuery).to receive(:call).and_return(...)&lt;/code&gt; in your spec.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;There is always a trade-off and moving to a separated class is not always a good idea, it adds a complexity layer to your code and has a maintainability cost, use this pattern with caution, and enjoy your extendable code.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>pattern</category>
      <category>query</category>
    </item>
    <item>
      <title>Design Patterns with Ruby on Rails part 1: Introduction and Policy Object</title>
      <dc:creator>Renata Marques</dc:creator>
      <pubDate>Mon, 22 Jun 2020 01:01:20 +0000</pubDate>
      <link>https://dev.to/renatamarques97/design-patterns-with-ruby-on-rails-part-1-introduction-and-policy-object-1c37</link>
      <guid>https://dev.to/renatamarques97/design-patterns-with-ruby-on-rails-part-1-introduction-and-policy-object-1c37</guid>
      <description>&lt;p&gt;This post is the first part of a series of posts about design patterns with Ruby on Rails.&lt;br&gt;
See other parts here:&lt;br&gt;
&lt;a href="https://dev.to/renatamarques97/design-patterns-with-ruby-on-rails-part-2-query-object-1h65"&gt;Part 2&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  What are design patterns?
&lt;/h4&gt;

&lt;p&gt;A pattern is the formalization of a problem/solution pair, used to make an object-oriented design decision.&lt;br&gt;
In sum, patterns are a set of general rules to achieve something that is easily repeatable for other developers.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why design patterns are important?
&lt;/h4&gt;

&lt;p&gt;First, the purpose of a pattern is to codify existing design knowledge so that developers are not constantly reinventing the wheel.&lt;br&gt;
Second, design patterns make communication between designers more efficient.&lt;br&gt;
Untested fat models, controllers, helpers, and views are a technical disaster, if you are not testing your code, it’s harder to see the need for using patterns.&lt;br&gt;
And how can you obtain design patterns benefits? applying these concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Isolation: if the logic related to database queries is isolated then you can easily use stubs
testing. The same rule applies to stuff like indexing or the 3rd part code.&lt;/li&gt;
&lt;li&gt;Readability: you can say what the given code is doing in general only by reading the
class name.&lt;/li&gt;
&lt;li&gt;Extendability: it’s easy to modify the existing code and there is no need to change the logic
in many places.&lt;/li&gt;
&lt;li&gt;Single Responsibility: a method or a class has to be responsible only for one action.&lt;/li&gt;
&lt;li&gt;Testability: thanks for the benefits mentioned, it becomes easier because we have to test only a small portion instead of large methods, connect to the external services and do the business logic at the same time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Policy Object
&lt;/h3&gt;

&lt;p&gt;Let’s begin with the simplest pattern, policy object is a pattern to deal with permissions, roles, and policies, you can use each time you have to check if something or someone is allowed to do the action. Gems like pundit, Cancan, and Cancancan implement this pattern.&lt;/p&gt;
&lt;h4&gt;
  
  
  Naming Convention
&lt;/h4&gt;

&lt;p&gt;The filename usually has &lt;code&gt;_policy&lt;/code&gt; suffix applied and the class with &lt;code&gt;Policy&lt;/code&gt; at&lt;br&gt;
the end. The method names always end with &lt;code&gt;?&lt;/code&gt; character.&lt;br&gt;
e.g.: &lt;code&gt;PostsPolicy#web_section?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A pure policy object is defined by these simple rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the return has to be a boolean value&lt;/li&gt;
&lt;li&gt;the logic has to be simple&lt;/li&gt;
&lt;li&gt;inside the method, we should only call methods on the passed objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;e.g.:&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;PostsPolicy&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;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&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;web_section?&lt;/span&gt;
    &lt;span class="n"&gt;active?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="vi"&gt;@post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;section&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="err"&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;active?&lt;/span&gt;
    &lt;span class="vi"&gt;@posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;active: &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;pending: &lt;/span&gt;&lt;span class="kp"&gt;false&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;Simply calling other methods and comparing using the data, this is the main purpose of policy object.&lt;br&gt;
They are light, simple pure Ruby objects, used for managing permissions across the project.&lt;br&gt;
They are also easy to test and a perfect replacement for complex conditions.&lt;/p&gt;

&lt;p&gt;An example of a complex condition:&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;PostsController&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;create&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="vi"&gt;@blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;moderator&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verified_email&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="c1"&gt;# create&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;The above condition checks are long, ugly, and unreadable, the policy object pattern can be applied.&lt;/p&gt;

&lt;p&gt;Let’s begin creating &lt;code&gt;PostsCreationPolicy&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;PostsCreationPolicy&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:blog&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blog&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="vi"&gt;@blog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blog&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create?&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="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new&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="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;create?&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;create?&lt;/span&gt;
    &lt;span class="n"&gt;blog_with_authors?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;author_is_allowed?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;blog_with_authors?&lt;/span&gt;
    &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;author_is_allowed?&lt;/span&gt;
    &lt;span class="n"&gt;is_admin?&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;moderator_is_verified?&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;is_admin?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="err"&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;moderator_is_verified?&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;moderator&lt;/span&gt;&lt;span class="sb"&gt;` &amp;amp;&amp;amp; user.verified_email
  end
end
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;our controller with the policy object looks like 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;PostsController&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;create&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;PostsCreationPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;#create&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;h4&gt;
  
  
  Policies in models
&lt;/h4&gt;

&lt;p&gt;Another way of refactoring complex queries is by creating small policy methods on the model 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;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_admin?&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="err"&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;is_moderator?&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;moderator&lt;/span&gt;&lt;span class="err"&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;is_authorable?&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_admin?&lt;/span&gt;

    &lt;span class="n"&gt;is_moderator?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;verified_email&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;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;Blog&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;live?&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;live&lt;/span&gt;&lt;span class="err"&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;any_authors?&lt;/span&gt;
    &lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any?&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;publishable?&lt;/span&gt;
    &lt;span class="n"&gt;live?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;any_authors?&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 we can refactor our controller:&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;PostsController&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;create&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@blog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publishable?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_authorable?&lt;/span&gt;
     &lt;span class="c1"&gt;# create&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;As you can see, it’s a much smaller and readable way to write the same logic.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;The policy pattern is a small concept that gives big results. Consider apply policy object each time you have to deal with complex conditions.&lt;br&gt;
When it comes to testing with RSpec, you don’t need to use database records, your policies are pure-ruby objects and your tests are going to be fast.&lt;/p&gt;

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