<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sparsh Garg</title>
    <description>The latest articles on Forem by Sparsh Garg (@sparsh9).</description>
    <link>https://forem.com/sparsh9</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%2F391704%2F67138e8e-1598-45f1-82fa-68fa4a93d2ea.jpg</url>
      <title>Forem: Sparsh Garg</title>
      <link>https://forem.com/sparsh9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sparsh9"/>
    <language>en</language>
    <item>
      <title>I Built and Published My First Ruby Gem: Rails API Profiler 🚀</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Tue, 13 Jan 2026 09:29:52 +0000</pubDate>
      <link>https://forem.com/sparsh9/i-built-and-published-my-first-ruby-gem-rails-api-profiler-18n4</link>
      <guid>https://forem.com/sparsh9/i-built-and-published-my-first-ruby-gem-rails-api-profiler-18n4</guid>
      <description>&lt;p&gt;I had been thinking about building a Ruby gem for a long time, but like many developers, I kept postponing it.&lt;/p&gt;

&lt;p&gt;Eventually, I decided to stop overthinking and &lt;strong&gt;just ship&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That decision led to my first Ruby gem: &lt;strong&gt;rails_api_profiler&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❓ The Problem
&lt;/h2&gt;

&lt;p&gt;While working on Rails API applications, I often wanted quick answers to simple questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which API endpoints are slow?&lt;/li&gt;
&lt;li&gt;How many database queries does a request trigger?&lt;/li&gt;
&lt;li&gt;Is the bottleneck in application code or the database?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full APM tools are powerful, but sometimes you just need &lt;strong&gt;lightweight, local insight&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 What the Gem Does
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rails_api_profiler&lt;/code&gt; is a &lt;strong&gt;middleware-based performance profiler&lt;/strong&gt; for Rails APIs.&lt;/p&gt;

&lt;p&gt;It logs, per request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request duration&lt;/li&gt;
&lt;li&gt;ActiveRecord query count&lt;/li&gt;
&lt;li&gt;Total database execution time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No controller changes. No monkey patching. Minimal setup.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📄 Example Output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[RailsApiProfiler] {
  :method=&amp;gt;"GET",
  :path=&amp;gt;"/api/v1/users",
  :status=&amp;gt;200,
  :duration_ms=&amp;gt;183.21,
  :db_queries=&amp;gt;7,
  :db_time_ms=&amp;gt;41.8
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ How It Works (Briefly)
&lt;/h2&gt;

&lt;p&gt;Under the hood, the gem uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rack middleware to measure request time&lt;/li&gt;
&lt;li&gt;ActiveSupport::Notifications to track SQL queries&lt;/li&gt;
&lt;li&gt;Thread-local storage for request-scoped stats&lt;/li&gt;
&lt;li&gt;A Railtie for automatic Rails integration&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 What I Learned
&lt;/h2&gt;

&lt;p&gt;Building this gem helped me understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rails middleware and instrumentation&lt;/li&gt;
&lt;li&gt;How to structure Rails-compatible gems&lt;/li&gt;
&lt;li&gt;Why shipping early beats waiting for perfection&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Try It Out
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RubyGems: &lt;a href="https://rubygems.org/gems/rails_api_profiler" rel="noopener noreferrer"&gt;https://rubygems.org/gems/rails_api_profiler&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/sparsh9/rails-api-profiler" rel="noopener noreferrer"&gt;https://github.com/sparsh9/rails-api-profiler&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback and contributions are welcome 🙌&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>MongoDB vs PostgreSQL JSONB: A Deep Dive into Performance and Use Cases</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Fri, 13 Jun 2025 07:34:54 +0000</pubDate>
      <link>https://forem.com/sparsh9/mongodb-vs-postgresql-jsonb-a-deep-dive-into-performance-and-use-cases-5bge</link>
      <guid>https://forem.com/sparsh9/mongodb-vs-postgresql-jsonb-a-deep-dive-into-performance-and-use-cases-5bge</guid>
      <description>&lt;p&gt;In the age of flexible data models and evolving application needs, developers often debate: &lt;em&gt;"Should I use MongoDB or PostgreSQL for JSON-like data?"&lt;/em&gt; While both databases support storing JSON data, their underlying design, performance characteristics, and use cases vary widely.&lt;/p&gt;

&lt;p&gt;This post will help you understand the &lt;strong&gt;core differences&lt;/strong&gt;, &lt;strong&gt;performance implications&lt;/strong&gt;, and &lt;strong&gt;when to choose what&lt;/strong&gt; based on your project needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧬 Storage and Internal Representation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;PostgreSQL (JSONB)&lt;/th&gt;
&lt;th&gt;MongoDB (BSON)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Binary JSON (compressed, indexed)&lt;/td&gt;
&lt;td&gt;BSON (Binary JSON with additional types)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Overhead&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate, especially with indexing&lt;/td&gt;
&lt;td&gt;Minimal, optimized for document storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Write Characteristics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slower due to WAL, ACID compliance&lt;/td&gt;
&lt;td&gt;Fast, low write amplification&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; MongoDB is optimized for document storage, while PostgreSQL adds JSON capabilities to a relational core.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Indexing and Query Performance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Indexing JSON&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GIN indexes on JSONB fields&lt;/td&gt;
&lt;td&gt;Native indexing on nested fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Querying Nested Fields&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Operators like &lt;code&gt;-&amp;gt;&lt;/code&gt;, &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Dot notation like &lt;code&gt;user.address.city&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Index Coverage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Partial for JSONB&lt;/td&gt;
&lt;td&gt;Full for indexed paths&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; MongoDB excels in querying deeply nested fields, especially with proper indexes.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⏱️ Read &amp;amp; Write Performance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Single Doc Read&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slower if JSONB is not indexed&lt;/td&gt;
&lt;td&gt;Fast and efficient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bulk Read&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good, slows with deep JSON nesting&lt;/td&gt;
&lt;td&gt;Very good with dot-notation queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Write Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slower (ACID overhead)&lt;/td&gt;
&lt;td&gt;Faster (schema-less design)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; MongoDB leads in both read and write speed for JSON-heavy applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Schema Flexibility
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema Evolution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual (migrations needed)&lt;/td&gt;
&lt;td&gt;Native, schema-less&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strong schema enforcement&lt;/td&gt;
&lt;td&gt;Optional, supports JSON schema validation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; MongoDB is great for evolving data models; PostgreSQL is ideal for structured, validated data.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡️ Transactions and Integrity
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ACID Transactions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fully supported&lt;/td&gt;
&lt;td&gt;Supported (since v4.0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Consistency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strong, mature&lt;/td&gt;
&lt;td&gt;Good, but less mature in distributed setups&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; PostgreSQL is your go-to when you need guaranteed integrity across multiple rows or tables.&lt;/p&gt;




&lt;h2&gt;
  
  
  📈 Scaling and Distribution
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;th&gt;MongoDB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Read Scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual (read replicas)&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Write Scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited (scale-up)&lt;/td&gt;
&lt;td&gt;Sharding (scale-out)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Geo Distribution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires tooling&lt;/td&gt;
&lt;td&gt;First-class support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; MongoDB is better suited for distributed, horizontally scalable applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ When to Use What?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Choose &lt;strong&gt;MongoDB&lt;/strong&gt; if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Your data is semi-structured or varies often&lt;/li&gt;
&lt;li&gt;You need high-speed reads/writes with nested documents&lt;/li&gt;
&lt;li&gt;Your application evolves rapidly&lt;/li&gt;
&lt;li&gt;You need to scale horizontally&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose &lt;strong&gt;PostgreSQL&lt;/strong&gt; if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You require strong consistency and complex joins&lt;/li&gt;
&lt;li&gt;Your data is mostly relational with some flexible fields&lt;/li&gt;
&lt;li&gt;You need robust reporting, window functions, or transactions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;While PostgreSQL has powerful JSON capabilities, it still operates within a relational model. MongoDB, on the other hand, is purpose-built for flexibility and performance with document-based data.&lt;/p&gt;

&lt;p&gt;In the end, the best database is the one that fits your specific use case — and now you’re better equipped to make that decision.&lt;/p&gt;

</description>
      <category>database</category>
      <category>programming</category>
      <category>sql</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>How YouTube Might Track “Most Replayed” Parts of a Video — in Ruby on Rails</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Thu, 15 May 2025 10:16:20 +0000</pubDate>
      <link>https://forem.com/sparsh9/how-youtube-might-track-most-replayed-parts-of-a-video-in-ruby-on-rails-2oc0</link>
      <guid>https://forem.com/sparsh9/how-youtube-might-track-most-replayed-parts-of-a-video-in-ruby-on-rails-2oc0</guid>
      <description>&lt;p&gt;Have you ever noticed the &lt;strong&gt;spiky graph&lt;/strong&gt; above the YouTube timeline showing &lt;strong&gt;"Most Replayed"&lt;/strong&gt; sections?&lt;/p&gt;

&lt;p&gt;In this post, we’ll build a simplified version of that system using &lt;strong&gt;Ruby on Rails&lt;/strong&gt; — to track, store, and visualize which parts of a video are being re-watched the most.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Step 1: Database Design
&lt;/h2&gt;

&lt;p&gt;We'll use two tables:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;videos&lt;/code&gt; – to store video metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;video_interactions&lt;/code&gt; – to log when a user scrubs, replays, or pauses at a specific second&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ✅ Migration: &lt;code&gt;videos&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# db/migrate/20250515120000_create_videos.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateVideos&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;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:videos&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="ss"&gt;:duration_seconds&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt; &lt;span class="ss"&gt;:uploaded_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;to_table: :users&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&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;h3&gt;
  
  
  ✅ Migration: &lt;code&gt;video_interactions&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# db/migrate/20250515120500_create_video_interactions.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateVideoInteractions&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;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:video_interactions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt; &lt;span class="ss"&gt;:video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;foreign_key: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;references&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;foreign_key: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:interaction_type&lt;/span&gt;  &lt;span class="c1"&gt;# e.g. 'replay', 'scrub'&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="ss"&gt;:timestamp_in_video&lt;/span&gt;  &lt;span class="c1"&gt;# second in timeline&lt;/span&gt;

      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&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;h2&gt;
  
  
  🧠 Step 2: Models
&lt;/h2&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/video.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Video&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;:video_interactions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/video_interaction.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoInteraction&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;:video&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="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;optional: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="ss"&gt;interaction_type: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;replay: &lt;/span&gt;&lt;span class="s1"&gt;'replay'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;scrub: &lt;/span&gt;&lt;span class="s1"&gt;'scrub'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;pause: &lt;/span&gt;&lt;span class="s1"&gt;'pause'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:timestamp_in_video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔁 Step 3: API Endpoint to Track Interactions
&lt;/h2&gt;

&lt;p&gt;Let’s make an endpoint to log interactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:videos&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:video_interactions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/controllers/video_interactions_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoInteractionsController&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="n"&gt;interaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;VideoInteraction&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="n"&gt;interaction_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :created&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;errors: &lt;/span&gt;&lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;full_messages&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;status: :unprocessable_entity&lt;/span&gt;
    &lt;span class="k"&gt;end&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;interaction_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:video_interaction&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;:video_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;:user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;:interaction_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;:timestamp_in_video&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;h2&gt;
  
  
  📈 Step 4: Aggregating the "Most Replayed" Data
&lt;/h2&gt;

&lt;p&gt;Now let’s create a method to find which parts of the video were replayed the most.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/video.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;replay_heatmap&lt;/span&gt;
  &lt;span class="n"&gt;video_interactions&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;interaction_type: &lt;/span&gt;&lt;span class="s1"&gt;'replay'&lt;/span&gt;&lt;span class="p"&gt;)&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;:timestamp_in_video&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:timestamp_in_video&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&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;most_replayed_second&lt;/span&gt;
  &lt;span class="n"&gt;replay_heatmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max_by&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&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 gives you a hash like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;6&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;7&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# 👈 most replayed second&lt;/span&gt;
  &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💻 Step 5: Visualizing on the Frontend
&lt;/h2&gt;

&lt;p&gt;You can send the &lt;code&gt;replay_heatmap&lt;/code&gt; hash to your frontend via an API, and render a chart using any JS library like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chart.js&lt;/li&gt;
&lt;li&gt;ApexCharts&lt;/li&gt;
&lt;li&gt;D3.js
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;GET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/videos/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="err"&gt;/replay_heatmap&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"6"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"7"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"8"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then show a &lt;strong&gt;hoverable graph&lt;/strong&gt; above your video player like YouTube.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Bonus: Background Summary Table (Optional)
&lt;/h2&gt;

&lt;p&gt;To speed up performance on popular videos, you can pre-aggregate data using a background job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails generate model VideoReplaySummary video:references timestamp_in_video:integer replay_count:integer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a job (e.g. with Sidekiq or ActiveJob) to refresh this hourly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Testing It Locally
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;curl&lt;/code&gt; or Postman to simulate a replay:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3000/videos/1/video_interactions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "video_interaction": {
      "user_id": 1,
      "interaction_type": "replay",
      "timestamp_in_video": 142
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;videos&lt;/code&gt; table&lt;/td&gt;
&lt;td&gt;Stores basic video info&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;video_interactions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Logs every replay/scrub with timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aggregation method&lt;/td&gt;
&lt;td&gt;Groups interactions by timestamp for heatmap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visualization&lt;/td&gt;
&lt;td&gt;Displays the graph on video timeline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




</description>
      <category>programming</category>
      <category>database</category>
      <category>webdev</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Capistrano: The Ultimate Guide to Automated Deployments for Rails Applications</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Wed, 13 Nov 2024 07:15:22 +0000</pubDate>
      <link>https://forem.com/sparsh9/capistrano-the-ultimate-guide-to-automated-deployments-for-rails-applications-1ejh</link>
      <guid>https://forem.com/sparsh9/capistrano-the-ultimate-guide-to-automated-deployments-for-rails-applications-1ejh</guid>
      <description>&lt;p&gt;Deploying web applications manually can be a time-consuming and error-prone process. This is where &lt;strong&gt;Capistrano&lt;/strong&gt; comes into play — a powerful Ruby-based tool designed to automate and simplify the deployment of web applications. In this comprehensive guide, we’ll explore what Capistrano is, how it works, its key features, and provide a step-by-step tutorial with practical examples to help you set it up for your Ruby on Rails application.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Capistrano?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Capistrano is an open-source tool for automating the deployment of web applications to remote servers via SSH. It streamlines repetitive tasks such as code fetching, dependency installation, database migrations, and server restarts, making the deployment process fast, reliable, and consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Features of Capistrano:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated Deployment:&lt;/strong&gt; Reduces human error by automating repetitive deployment tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-server Support:&lt;/strong&gt; Easily deploys applications across multiple servers and roles (e.g., &lt;code&gt;web&lt;/code&gt;, &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rollbacks:&lt;/strong&gt; Allows you to quickly revert to previous releases in case of deployment failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Tasks:&lt;/strong&gt; Provides flexibility to define custom tasks tailored to your application needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration with Popular Tools:&lt;/strong&gt; Supports plugins like &lt;code&gt;capistrano-rails&lt;/code&gt;, &lt;code&gt;capistrano-rvm&lt;/code&gt;, and &lt;code&gt;capistrano-bundler&lt;/code&gt; for Rails-specific tasks and Ruby version management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Getting Started with Capistrano&lt;/strong&gt;
&lt;/h2&gt;

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

&lt;p&gt;First, add Capistrano and necessary plugins to your Rails project’s &lt;code&gt;Gemfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 3.17'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-rails'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 1.6'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-rvm'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 0.2.0'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-bundler'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 2.0'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'capistrano-passenger'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 0.2'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;bundle install&lt;/code&gt; to install the gems.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Up Capistrano&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To initialize Capistrano in your project, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command generates the following files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Capfile&lt;/code&gt;&lt;/strong&gt;: The main configuration file where plugins are required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;config/deploy.rb&lt;/code&gt;&lt;/strong&gt;: Global configuration settings for the deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;config/deploy/production.rb&lt;/code&gt;&lt;/strong&gt;: Environment-specific configuration (e.g., for production).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Capistrano Configuration Files Explained&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Capfile&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Capfile&lt;/code&gt; is where you require necessary libraries and plugins:&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="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/setup'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/deploy'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/rvm'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/bundler'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/rails'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'capistrano/passenger'&lt;/span&gt;

&lt;span class="n"&gt;install_plugin&lt;/span&gt; &lt;span class="no"&gt;Capistrano&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RVM&lt;/span&gt;
&lt;span class="n"&gt;install_plugin&lt;/span&gt; &lt;span class="no"&gt;Capistrano&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Bundler&lt;/span&gt;
&lt;span class="n"&gt;install_plugin&lt;/span&gt; &lt;span class="no"&gt;Capistrano&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migrations&lt;/span&gt;
&lt;span class="n"&gt;install_plugin&lt;/span&gt; &lt;span class="no"&gt;Capistrano&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Passenger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Global Configuration (&lt;code&gt;config/deploy.rb&lt;/code&gt;)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;deploy.rb&lt;/code&gt; file defines the main configuration for your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"my_app"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:repo_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"git@github.com:username/my_app.git"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:deploy_to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/var/www/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:application&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:branch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:format&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:pretty&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:log_level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:info&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:keep_releases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="c1"&gt;# RVM Configuration&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rvm_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rvm_ruby_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2.7.8'&lt;/span&gt;

&lt;span class="c1"&gt;# Linked Files &amp;amp; Directories&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:linked_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;%w{config/database.yml .env}&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:linked_dirs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sx"&gt;%w{log tmp/pids tmp/cache tmp/sockets public/system}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Environment Configuration (&lt;code&gt;config/deploy/production.rb&lt;/code&gt;)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This file specifies server details and environment-specific configurations:&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;server&lt;/span&gt; &lt;span class="s1"&gt;'123.45.67.89'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user: &lt;/span&gt;&lt;span class="s1"&gt;'deploy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;roles: &lt;/span&gt;&lt;span class="sx"&gt;%w{app web db}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;primary: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:rails_env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'production'&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:ssh_options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;keys: &lt;/span&gt;&lt;span class="sx"&gt;%w(~/.ssh/id_rsa)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;forward_agent: &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;auth_methods: &lt;/span&gt;&lt;span class="sx"&gt;%w(publickey)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Deployment Workflow Explained&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Capistrano follows a series of automated steps during the deployment process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setup:&lt;/strong&gt; Initializes the deployment structure on the server (directories like &lt;code&gt;/releases&lt;/code&gt; and &lt;code&gt;/shared&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch Code:&lt;/strong&gt; Pulls the latest code from the Git repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install Dependencies:&lt;/strong&gt; Uses Bundler to install Ruby gems (&lt;code&gt;bundle install&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run Migrations:&lt;/strong&gt; Executes &lt;code&gt;rake db:migrate&lt;/code&gt; to update the database schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precompile Assets:&lt;/strong&gt; Runs &lt;code&gt;rake assets:precompile&lt;/code&gt; for Rails applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart Server:&lt;/strong&gt; Restarts the application server (e.g., Passenger or Puma).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleanup:&lt;/strong&gt; Removes old releases to free up disk space.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To deploy your application, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Rolling Back a Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If something goes wrong, you can quickly roll back to the previous release:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Custom Tasks in Capistrano&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Capistrano allows you to define custom tasks to fit your deployment needs. Here are some useful examples:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example 1: Clearing Sidekiq Logs&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:logs&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Clear Sidekiq logs"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:clear_sidekiq_log&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"echo '' &amp;gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/log/sidekiq.log"&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Sidekiq logs cleared!"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="s1"&gt;'deploy:finished'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'logs:clear_sidekiq_log'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Example 2: Update File Permissions&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Update permissions"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:update_permissions&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"chmod -R 755 &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;release_path&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;"Permissions updated for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;release_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="s1"&gt;'deploy:finishing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'deploy:update_permissions'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Example 3: Restarting Nginx&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:nginx&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Restart Nginx"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:restart&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:web&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"sudo systemctl restart nginx"&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Nginx restarted successfully!"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="s1"&gt;'deploy:finishing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'nginx:restart'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Troubleshooting Common Issues&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. SSH Authentication Errors&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ensure your SSH key is correctly configured and added to the SSH agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Permission Errors&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you encounter permission errors, adjust the permissions of the deployment directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; deploy:deploy /var/www/my_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Git Repository Access Issues&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Verify that your SSH key has access to the Git repository and SSH agent forwarding is enabled:&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;set&lt;/span&gt; &lt;span class="ss"&gt;:ssh_options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;forward_agent: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices for Using Capistrano&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use SSH Key Forwarding:&lt;/strong&gt; This avoids storing your private SSH key on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limit Release History:&lt;/strong&gt; Use &lt;code&gt;set :keep_releases, 5&lt;/code&gt; to avoid filling up the server with old releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Deployments Locally:&lt;/strong&gt; Use &lt;code&gt;--dry-run&lt;/code&gt; to safely test your deployment commands without making changes.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Capistrano is a robust and versatile tool that can handle complex deployment scenarios with ease. By leveraging its automation capabilities, you can save time, reduce human errors, and focus more on building features rather than managing deployments. With proper configuration and custom tasks, Capistrano can fit seamlessly into your DevOps workflow, making your deployments reliable and efficient.&lt;/p&gt;

&lt;p&gt;Start using Capistrano today and take your deployment process to the next level. 🚀&lt;/p&gt;

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

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>capistrano</category>
      <category>programming</category>
    </item>
    <item>
      <title>Unlock Superior Security: Implementing 2FA in Ruby on Rails with a Twist!</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Sun, 21 Apr 2024 08:24:20 +0000</pubDate>
      <link>https://forem.com/sparsh9/unlock-superior-security-implementing-2fa-in-ruby-on-rails-with-a-twist-3gnf</link>
      <guid>https://forem.com/sparsh9/unlock-superior-security-implementing-2fa-in-ruby-on-rails-with-a-twist-3gnf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;Welcome to our interactive guide on enhancing your Ruby on Rails application's security with two-factor authentication (2FA)! In this engaging tutorial, we'll show you how to add an extra layer of protection using OTPs and QR codes. But wait, there's more! We'll also optimize the code and give the models a fresh new look! Let's dive in and make your app more secure and user-friendly!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: Setting up the ROTP Gem 🛠️&lt;/p&gt;

&lt;p&gt;Let's start by adding some magic to your Gemfile! 🧙‍♂️&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rotp'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;bundle install&lt;/code&gt; to install the ROTP gem and unlock the power of OTP generation in your Rails app!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Creating the User Model 🧑‍💼&lt;/p&gt;

&lt;p&gt;Meet your User model, the guardian of your app's security! 🛡️&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;ApplicationRecord&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:otp&lt;/span&gt;

  &lt;span class="n"&gt;before_create&lt;/span&gt; &lt;span class="ss"&gt;:create_passkey&lt;/span&gt;

  &lt;span class="c1"&gt;# Add methods for passkey creation and verification&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: Generating QR Codes with RQRCode 🌈&lt;/p&gt;

&lt;p&gt;Let's add some color to your authentication process with QR codes! 🌟&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rqrcode'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a QR code generation method in your QrController to make setting up 2FA a breeze! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;: Verifying OTPs on Login 🔒&lt;/p&gt;

&lt;p&gt;Time to put your 2FA to the test during login! 🚪&lt;/p&gt;

&lt;p&gt;Add the &lt;code&gt;verify_passkey&lt;/code&gt; method to your ApplicationController to ensure only the rightful users gain access! 🗝️&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimisation:
&lt;/h2&gt;

&lt;p&gt;💡&lt;/p&gt;

&lt;p&gt;Let's optimise the &lt;code&gt;passkey_verification&lt;/code&gt; method in the User model for better performance:&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="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;passkey_verification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;

  &lt;span class="n"&gt;totp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ROTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TOTP&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="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;passkey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;totp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&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;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;🎉&lt;/p&gt;

&lt;p&gt;Congratulations! You've successfully leveled up your app's security with 2FA in Ruby on Rails! 🚀 By following these steps and adding a touch of magic with gems like ROTP and RQRCode, you've made your app more secure and user-friendly. Keep exploring and enhancing your app's security to provide a top-notch experience for your users! 🌟&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Keeping Secrets Safe: The Importance of Encrypting API Data</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Wed, 22 Nov 2023 09:41:05 +0000</pubDate>
      <link>https://forem.com/sparsh9/keeping-secrets-safe-the-importance-of-encrypting-api-data-41e</link>
      <guid>https://forem.com/sparsh9/keeping-secrets-safe-the-importance-of-encrypting-api-data-41e</guid>
      <description>&lt;p&gt;In the world of apps and websites, keeping secrets safe is like hiding treasures from sneaky pirates. When you get information from an API (like a secret message from a friend), it's essential to keep it safe on your end. &lt;/p&gt;

&lt;p&gt;Let's talk about why it's crucial to always take encrypted data from an API and decrypt it on your backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Secret Code: Encryption
&lt;/h2&gt;

&lt;p&gt;Imagine you have a magical way to turn your messages into secret codes before sending them to your friends. This secret code, called encryption, keeps your messages safe from prying eyes. It's like putting your message inside a treasure chest that only you and your friend can open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Always Choose Encryption?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Guarding Secrets: When you get data from an API, it might contain important information—like user passwords or special messages. If this data is encrypted, it's like having a secret map that only you can read.&lt;/li&gt;
&lt;li&gt;Protection from Pirates: Just like pirates try to steal treasures, there are bad folks on the internet trying to steal information. Encryption is your shield, protecting your data even if someone tries to sneak a peek.&lt;/li&gt;
&lt;li&gt;Trustworthy Communication: If you're talking to your friend through a messenger bird (API), you'd want your message to be in code. This way, even if the bird stops at other places, your secret message stays safe until it reaches your friend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example: Super-Secret Messaging API
&lt;/h2&gt;

&lt;p&gt;Let's imagine a real-life scenario. You have a messaging app, and your friend's API sends you encrypted messages. Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Getting an encrypted message from the API
require 'net/http'
require 'uri'

api_url = 'https://super-secret-messenger-api/messages'
uri = URI.parse(api_url)

# Make a request to the API
response = Net::HTTP.get_response(uri)
encrypted_message = response.body

# Decrypting the message on your backend
def decrypt(encrypted_message, your_secret_key)
  # Imagine using a special decoder here
  # Replace 'your_secret_key' with your actual secret key
  decrypted_message = magic_decoding_spell(encrypted_message, your_secret_key)
  puts "Decrypted Message: #{decrypted_message}"
end

# Replace 'your_secret_key' with the actual secret key
decrypt(encrypted_message, 'your_secret_key')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the API sends you an encrypted message, and you use a magical decoding spell (decryption) on your end to read the original message. It's like opening a treasure chest and finding your friend's secret note inside.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Keep Your Secrets Safe
&lt;/h2&gt;

&lt;p&gt;In the grand adventure of building apps and websites, always remember the importance of keeping your secrets safe. When dealing with data from an API, make sure it's like a secret map that only you can understand. Choose encryption, use your magical decoding spells wisely, and keep the treasures of information safe from the internet pirates!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>security</category>
      <category>api</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Optimising Git Usage: Essential Tips for Efficient Code Management from Local to Global</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Wed, 30 Aug 2023 13:09:57 +0000</pubDate>
      <link>https://forem.com/sparsh9/optimising-git-usage-essential-tips-for-efficient-code-management-from-local-to-global-2j93</link>
      <guid>https://forem.com/sparsh9/optimising-git-usage-essential-tips-for-efficient-code-management-from-local-to-global-2j93</guid>
      <description>&lt;p&gt;Hello aspiring developers!&lt;/p&gt;

&lt;p&gt;Embarking on your software development journey means embracing tools like GitHub, a powerful platform that fosters collaboration and version control. This article is designed to guide beginners in the art of using GitHub commands effectively, ensuring smoother collaboration and better code management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Creating a New Branch for Development:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When starting a new feature or addressing an issue, creating a new branch helps keep your work isolated from the main codebase. Use the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a new branch and switch to it&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; new-feature

&lt;span class="c"&gt;# Push the new branch to the remote repository&lt;/span&gt;
git push origin new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Always Pull from Origin:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before starting any development, ensure you're working with the latest code. Pulling from the remote repository prevents conflicts down the line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Switch to your development branch&lt;/span&gt;
git checkout new-feature

&lt;span class="c"&gt;# Pull the latest changes from the remote repository&lt;/span&gt;
git pull origin new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Committing Only Necessary Files:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep your commits focused and concise by only including relevant changes. Use &lt;code&gt;git status&lt;/code&gt; to see modified files and &lt;code&gt;git add&lt;/code&gt; to stage them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage specific files for commit&lt;/span&gt;
git add file1.js file2.css

&lt;span class="c"&gt;# Commit the staged changes&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Implemented feature X and updated styling"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Adding a Proper Commit Message:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Writing informative commit messages helps you and your collaborators understand the purpose of each change. Follow this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Short description of your changes

More detailed explanation, if needed.
Issue #123"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Resolving Merge Conflicts via Terminal:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Conflicts can arise when merging branches. To resolve them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fetch the latest changes from the remote repository&lt;/span&gt;
git fetch origin

&lt;span class="c"&gt;# Switch to your development branch&lt;/span&gt;
git checkout new-feature

&lt;span class="c"&gt;# Merge the changes from the main branch&lt;/span&gt;
git merge origin/main

&lt;span class="c"&gt;# Resolve any conflicts in your code files&lt;/span&gt;

&lt;span class="c"&gt;# After resolving, commit the changes&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Resolved merge conflicts"&lt;/span&gt;

&lt;span class="c"&gt;# Push the resolved changes to the remote repository&lt;/span&gt;
git push origin new-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember, practice makes perfect. Embrace these GitHub commands in your workflow to streamline collaboration and manage your codebase effectively. As you become more comfortable, you'll find yourself contributing seamlessly to projects and collaborating with confidence.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀👩‍💻👨‍💻&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Caching in Ruby on Rails: Boosting Performance and Efficiency</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Wed, 30 Aug 2023 12:03:55 +0000</pubDate>
      <link>https://forem.com/sparsh9/understanding-caching-in-ruby-on-rails-boosting-performance-and-efficiency-47cn</link>
      <guid>https://forem.com/sparsh9/understanding-caching-in-ruby-on-rails-boosting-performance-and-efficiency-47cn</guid>
      <description>&lt;p&gt;Caching is a powerful technique that can significantly enhance the performance and efficiency of your Ruby on Rails applications. By storing frequently accessed data or rendered views, you can reduce database queries and server processing, resulting in faster response times for your users. In this article, we'll explore caching in Ruby on Rails and provide code snippets to illustrate how to implement caching effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Caching Basics:
&lt;/h2&gt;

&lt;p&gt;Caching involves storing copies of data in a faster storage layer (such as memory) so that future requests for the same data can be served quickly without the need for time-consuming computations or database queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Types of Caching in Rails:
&lt;/h2&gt;

&lt;p&gt;Rails offers several caching mechanisms:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Page Caching&lt;/strong&gt;: Caches entire HTML pages as static files. Ideal for pages with content that rarely changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Action Caching&lt;/strong&gt;: Caches the output of controller actions. Useful when you have dynamic content that doesn't change frequently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fragment Caching&lt;/strong&gt;: Caches specific parts (fragments) of a view. Great for components shared across different views.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model Caching&lt;/strong&gt;: Caches individual records or collections fetched from the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Implementing Fragment Caching:
&lt;/h2&gt;

&lt;p&gt;Fragment caching is commonly used to cache specific parts of a view. Let's consider a scenario where we want to cache the list of recent blog posts on our homepage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- app/views/home/index.html.erb --&amp;gt;

&amp;lt;% cache 'recent_blog_posts' do %&amp;gt;
  &amp;lt;h2&amp;gt;Recent Blog Posts&amp;lt;/h2&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;% @recent_posts.each do |post| %&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;%= link_to post.title, post_path(post) %&amp;gt;&amp;lt;/li&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the content within the cache block will be cached. If the underlying data changes, Rails will regenerate the cache. You can also set an expiration time for the cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Using Low-Level Caching:
&lt;/h2&gt;

&lt;p&gt;Rails provides low-level caching methods that allow you to manually manage cache entries. For instance, you can cache the result of a complex database query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/controllers/posts_controller.rb

def index
  @posts = Rails.cache.fetch('all_posts', expires_in: 1.day) do
    Post.all
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, the result of &lt;strong&gt;Post.all&lt;/strong&gt; is cached with the key '&lt;strong&gt;all_posts&lt;/strong&gt;' for a day. Subsequent calls to the same key will fetch data from the cache rather than executing the query again.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Clearing the Cache:
&lt;/h2&gt;

&lt;p&gt;To maintain data consistency, it's important to clear the cache when relevant data changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rails.cache.delete('recent_blog_posts')  # Clear the cache for recent_blog_posts
Rails.cache.clear  # Clear the entire cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Caching is a fundamental technique for optimizing the performance of Ruby on Rails applications. By utilizing various caching strategies such as fragment caching and low-level caching, you can reduce database queries and improve response times. Keep in mind that while caching enhances performance, it requires careful consideration and management to ensure that cached data remains accurate and up-to-date.&lt;/p&gt;

&lt;p&gt;Incorporating caching into your Rails applications can greatly enhance user experience and server efficiency, making it a valuable skill for every Rails developer to master.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>Connecting Multiple Databases in Rails 5</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Tue, 29 Aug 2023 12:54:35 +0000</pubDate>
      <link>https://forem.com/sparsh9/connecting-multiple-databases-in-rails-5-1a0e</link>
      <guid>https://forem.com/sparsh9/connecting-multiple-databases-in-rails-5-1a0e</guid>
      <description>&lt;p&gt;Ruby on Rails is a powerful web framework that makes building web applications a breeze. In some scenarios, you might find yourself needing to work with multiple databases within a single Rails application. This could be due to various reasons, such as managing different types of data or segregating data for performance optimisation. In this article, we'll explore how to connect and interact with multiple databases in a Rails 5 application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Databases
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code snippets, let's set up the scenario. Imagine you have a Rails application that needs to interact with two separate databases: a primary database for user data and a secondary database for product information. Here's how you can configure your database.yml file to define the connection settings for both databases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# config/database.yml

default: &amp;amp;default
  adapter: postgresql
  encoding: unicode
  pool: &amp;lt;%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %&amp;gt;
  username: your_username
  password: your_password
  host: localhost

development:
  &amp;lt;&amp;lt;: *default
  database: primary_db_development

secondary_development:
  &amp;lt;&amp;lt;: *default
  database: secondary_db_development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above configuration, we have defined two separate sections: development for the primary database and secondary_development for the secondary database. Make sure to replace your_username and your_password with the appropriate credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Database Models
&lt;/h2&gt;

&lt;p&gt;Next, we need to create models for each of the databases. Let's create two models: User for the primary database and Product for the secondary database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/models/user.rb

class User &amp;lt; ApplicationRecord
  establish_connection :development # Connect to the primary database
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app/models/product.rb

class Product &amp;lt; ApplicationRecord
  establish_connection :secondary_development # Connect to the secondary database
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we use the establish_connection method to specify which database connection to use for each model. This way, the User model will use the primary database connection, and the Product model will use the secondary database connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performing Database Operations
&lt;/h2&gt;

&lt;p&gt;Now that we have our models set up, let's see how to perform basic database operations on each database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primary Database Operations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create a new user in the primary database
user = User.create(name: 'John Doe', email: 'john@example.com')

# Retrieve users from the primary database
users = User.where(age: 25)

# Update a user's information
user.update(name: 'Jane Doe')

# Delete a user
user.destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Secondary Database Operations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create a new product in the secondary database
product = Product.create(name: 'Widget', price: 19.99)

# Retrieve products from the secondary database
products = Product.where(category: 'Electronics')

# Update a product's information
product.update(price: 24.99)

# Delete a product
product.destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running Migrations
&lt;/h2&gt;

&lt;p&gt;When you're working with multiple databases, you need to run migrations separately for each database. To achieve this, you can specify the database connection when running migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails db:migrate          # Run migrations for the primary database
rails db:migrate RAILS_ENV=development_secondary # Run migrations for the secondary database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this article, we've explored how to connect and interact with multiple databases within a single Rails 5 application. By configuring the database.yml file, defining separate models for each database, and using the establish_connection method, you can seamlessly work with different databases in your application. Whether you're dealing with diverse data types or optimizing performance, Rails provides the flexibility you need to manage multiple databases effectively.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>database</category>
      <category>programming</category>
    </item>
    <item>
      <title>Using Database Level Associations v/s Active Record Associations in Ruby On Rails</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Tue, 07 Feb 2023 07:07:08 +0000</pubDate>
      <link>https://forem.com/sparsh9/using-database-level-associations-vs-active-record-associations-in-ruby-on-rails-44o6</link>
      <guid>https://forem.com/sparsh9/using-database-level-associations-vs-active-record-associations-in-ruby-on-rails-44o6</guid>
      <description>&lt;h2&gt;
  
  
  What are database level associations?
&lt;/h2&gt;

&lt;p&gt;Database level associations refers to relationships between tables in a database that are established through foreign keys. These relationships are defined and managed directly in the database schema.&lt;br&gt;
&lt;strong&gt;For example&lt;/strong&gt; - Suppose you have two tables in your database, &lt;em&gt;'users'&lt;/em&gt; and &lt;em&gt;'posts'&lt;/em&gt;, where each user can have multiple posts. So to establish a one-to-many relationship between these two tables, you can create a foreign key constraint in the &lt;em&gt;'posts'&lt;/em&gt; table that references the &lt;em&gt;'id'&lt;/em&gt; column in the &lt;em&gt;'users'&lt;/em&gt; table.&lt;/p&gt;
&lt;h2&gt;
  
  
  What are active record associations?
&lt;/h2&gt;

&lt;p&gt;Associations in rails allow you to specify relationships between your models and their related data in database. They are defined using ActiveRecord and are used to simplify the process of working with related data.&lt;br&gt;
&lt;strong&gt;For example&lt;/strong&gt; - Suppose you have two models in you application, &lt;em&gt;'User'&lt;/em&gt; and &lt;em&gt;'Post'&lt;/em&gt;, where each user can have multiple posts. To define their relationship you would add the following code to your &lt;em&gt;'User'&lt;/em&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class User &amp;lt; ApplicationRecord
  has_many :posts
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the following code to your &lt;em&gt;'Post'&lt;/em&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Post &amp;lt; ApplicationRecord
  belongs_to :user
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using database level associations
&lt;/h2&gt;

&lt;p&gt;Using database level associations has it's own advantage which make a huge difference&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: It can be faster than using ActiveRecord associations, especially in complex, multi-layer associations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fine-grained control&lt;/strong&gt;: It allow you to have fine-grained control over your database interactions, giving you the ability to optimise your database queries and interactions to meet the specific requirements of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: By avoiding the overhead of the ActiveRecord association abstractions, database-level associations can make your code simpler and easier to understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Increased flexibility&lt;/strong&gt;: With database-level associations, you are not limited to the abstractions provided by the framework and can implement custom relationships between your tables if needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: In large, high-performance applications, database-level associations can be more scalable than using ActiveRecord associations, especially in terms of memory usage and query performance.&lt;/p&gt;

&lt;p&gt;Apart from these benefits there are some drawbacks also, such as &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt;- Increased complexity by directly using database level associations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Schema Changes&lt;/strong&gt; - The need to change relationships directly in the database schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance&lt;/strong&gt; - It can make your code less maintainable because they are not as abstracted as ActiveRecord associations. You would have to write more raw SQL code, which can be error-prone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portability&lt;/strong&gt;: If you use database-level associations, it might be harder to switch to a different ORM (Object-Relational Mapping) framework or database in the future. ActiveRecord associations, on the other hand, provide a higher level of abstraction and are more portable.&lt;/p&gt;

&lt;p&gt;Ultimately, the choice between database-level associations and ActiveRecord associations will depend on the specific requirements of your application, such as performance, scalability, and maintainability.&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>career</category>
      <category>howto</category>
    </item>
    <item>
      <title>Pagination without using any gems in Ruby On Rails</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Sat, 28 Jan 2023 07:28:07 +0000</pubDate>
      <link>https://forem.com/sparsh9/pagination-using-sql-query-in-rails-ggb</link>
      <guid>https://forem.com/sparsh9/pagination-using-sql-query-in-rails-ggb</guid>
      <description>&lt;h2&gt;
  
  
  What is pagination?
&lt;/h2&gt;

&lt;p&gt;Pagination refers to the process of dividing a list of items into multiple pages that can be navigated through using buttons or links. This is commonly used for displaying large sets of data, such as search results or articles, in a more manageable format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why to use pagination?
&lt;/h2&gt;

&lt;p&gt;Pagination is used to improve the user experience and performance of a website by dividing large sets of data into smaller, more manageable chunks.&lt;/p&gt;

&lt;p&gt;User experience: Large lists of data can be overwhelming for users and make it difficult to find the information they are looking for. Pagination allows users to easily navigate through the data and find the specific information they need. It also allows users to quickly scan through the data to find relevant information.&lt;/p&gt;

&lt;p&gt;Performance: Loading large amounts of data at once can slow down a website, especially for users with slow internet connections. Pagination allows for smaller amounts of data to be loaded at a time, improving the overall performance of the website. Additionally, it helps to reduce the load on the server, which can also improve performance.&lt;/p&gt;

&lt;p&gt;Accessibility: Pagination also helps with accessibility, because it allows users to easily access the specific data they need and it enables them to skip irrelevant data.&lt;/p&gt;

&lt;p&gt;Search Engine Optimization: Search engines can also benefit from pagination because it allows them to crawl and index the content on a website more efficiently.&lt;/p&gt;

&lt;p&gt;In summary, Pagination improves the user experience, performance, accessibility, and search engine optimization of a website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pagination in Ruby On Rails
&lt;/h2&gt;

&lt;p&gt;In Ruby on Rails, pagination can be implemented using the "&lt;em&gt;will_paginate&lt;/em&gt;" gem or the "&lt;em&gt;kaminari&lt;/em&gt;" gem. Both of these gems provide a simple and easy way to add pagination to a Rails application.&lt;/p&gt;

&lt;p&gt;The "&lt;em&gt;will_paginate&lt;/em&gt;" gem adds a paginate method to the &lt;em&gt;ActiveRecord::Relation class&lt;/em&gt;, which can be used to paginate any database query. For example, to paginate a list of users, you would write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.paginate(:page =&amp;gt; params[:page], :per_page =&amp;gt; 10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "&lt;em&gt;kaminari&lt;/em&gt;" gem provides similar functionality, with a page method that can be used to paginate any database query. For example, to paginate a list of users, you would write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.page(params[:page]).per(10)

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

&lt;/div&gt;



&lt;p&gt;Once you have paginated your data, both gems provide helper methods for generating the HTML for the pagination links. In the views, you can use the &lt;em&gt;will_paginate&lt;/em&gt; or &lt;em&gt;kaminari_paginate&lt;/em&gt; helper method to generate the HTML for the pagination links.&lt;/p&gt;

&lt;p&gt;Both gems are well-documented and easy to use, and you can choose the one that better fits your needs or preferences.&lt;/p&gt;

&lt;p&gt;Additionally, Rails has built-in pagination feature in rails 6, which is called "built-in pagination" using the &lt;em&gt;pagy&lt;/em&gt; gem.&lt;/p&gt;

&lt;p&gt;But recently I have used one more method of pagination i.e using SQL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def show_method
     total_page = (ModelName.all.count.to_f / 5).ceil
     current_page = (params[:page] || 1).to_i
     per_page = 5
     records_fetch_point = (current_page - 1) * per_page
     model = ModelName.order(id: :desc).limit(per_page).offset(records_fetch_point)
     page = {
       page_number: current_page,
       per_page: per_page,
       total_page: total_page
     }
     if model.empty?
       render json: {error: 'No data found'}, status: :not_found
     else
       render json: {data: model, message: "Data", meta: page}, status: :ok
     end
   end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have used this method because :-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I wanted to try some custom method for pagination.&lt;/li&gt;
&lt;li&gt;Sometimes gems like pagy, kaminari, will_paginate does not work due to version or configuration issues.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Using Rails Model or SQL query in Ruby On Rails</title>
      <dc:creator>Sparsh Garg</dc:creator>
      <pubDate>Wed, 17 Aug 2022 06:53:00 +0000</pubDate>
      <link>https://forem.com/sparsh9/using-rails-model-or-sql-query-in-ruby-on-rails-5gie</link>
      <guid>https://forem.com/sparsh9/using-rails-model-or-sql-query-in-ruby-on-rails-5gie</guid>
      <description>&lt;p&gt;Although there can be multiple ways you can get data from your database, but here are two ways you can get data.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using Rails Model&lt;/strong&gt; -&amp;gt; In this method of data fetching we use rails model, which we create using &lt;code&gt;rails g model model_name&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def index
    @data = ModelName.all
    render_success_response @data
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In above piece of code&lt;/p&gt;

&lt;p&gt;index -&amp;gt; name of the method&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/data"&gt;@data&lt;/a&gt; -&amp;gt; name of variable to store the data&lt;/p&gt;

&lt;p&gt;.all -&amp;gt; rails method to get all the data from the respective table associated with the model&lt;/p&gt;

&lt;p&gt;render_success_response -&amp;gt; default rails method to render a success response&lt;/p&gt;

&lt;p&gt;Now there can be multiple methods we can use. Check out &lt;a href="https://devhints.io/rails-models"&gt;devhints&lt;/a&gt; for references.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using SQL Query&lt;/strong&gt; -&amp;gt; In this method of data fetching we use direct SQL queries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def index
    sql = "select * from table_name"
    @data = ActiveRecord::Base.connection.execute(sql)
    render_success_response @data
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In above piece of code&lt;/p&gt;

&lt;p&gt;ActiveRecord::Base.connection.execute() -&amp;gt; it is used to run sql queries in ruby on rails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
You can use both rails model or sql query in you code according to your use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://devhints.io/"&gt;Dev Hints&lt;/a&gt;&lt;/p&gt;

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