<?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: Colin Soleim</title>
    <description>The latest articles on DEV Community by Colin Soleim (@colinsoleim).</description>
    <link>https://dev.to/colinsoleim</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%2F322478%2Ffbd08dca-490a-43c4-b865-213b15de72f0.jpeg</url>
      <title>DEV Community: Colin Soleim</title>
      <link>https://dev.to/colinsoleim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/colinsoleim"/>
    <language>en</language>
    <item>
      <title>Setting Up Your Ruby on Rails Monolith for AI Development</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Sat, 14 Mar 2026 16:28:36 +0000</pubDate>
      <link>https://dev.to/colinsoleim/setting-up-your-ruby-on-rails-monolith-for-ai-development-5bga</link>
      <guid>https://dev.to/colinsoleim/setting-up-your-ruby-on-rails-monolith-for-ai-development-5bga</guid>
      <description>&lt;p&gt;As a software consultant who regularly work with enterprise Rails applications, I've spent the last year experimenting with ways to make large Rails monoliths more accessible to AI development tools like Claude Code, Cursor, and Windsurf. Through trial and error, we've discovered that preparing your codebase for AI requires deliberate architectural choices and workflow adjustments.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Split Your Monolith into namespaces with contextual CLAUDE.md or AGENT.md files at the root of each namespace&lt;/li&gt;
&lt;li&gt;Implement Guard with Fast, Focused Test Suites&lt;/li&gt;
&lt;li&gt;Implement Typed ActiveRecord Models with Sorbet or RBS&lt;/li&gt;
&lt;li&gt;Set Up Replit Agents for Non-Technical Stakeholders&lt;/li&gt;
&lt;li&gt;Build an AI-Friendly Service Layer Architecture&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I added more detailed descriptions in a blog post here:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://nextlinklabs.com/resources/insights/setting-up-your-ruby-on-rails-monolith-for-ai-development" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnextlinklabs.com%2Fhubfs%2FSlide%252016_9%2520-%25207.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://nextlinklabs.com/resources/insights/setting-up-your-ruby-on-rails-monolith-for-ai-development" rel="noopener noreferrer" class="c-link"&gt;
            Setting Up Your Ruby on Rails Monolith for AI Development
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Large Rails monoliths burn millions of tokens per AI session. These 5 architectural changes cut costs and boost AI suggestion quality by 3-4x.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnextlinklabs.com%2Fhubfs%2FNLL-favicon-1.png"&gt;
          nextlinklabs.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>rails</category>
    </item>
    <item>
      <title>10 Advanced Ruby on Rails Features</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Wed, 23 Apr 2025 10:45:15 +0000</pubDate>
      <link>https://dev.to/colinsoleim/10-advanced-ruby-on-rails-features-2h04</link>
      <guid>https://dev.to/colinsoleim/10-advanced-ruby-on-rails-features-2h04</guid>
      <description>&lt;p&gt;I recently saw a great article posted by an engineer about advanced tips and tricks in Python (&lt;a href="https://blog.edward-li.com/tech/advanced-python-features/" rel="noopener noreferrer"&gt;https://blog.edward-li.com/tech/advanced-python-features/&lt;/a&gt;) which got me thinking about similar features in Ruby on Rails.&lt;/p&gt;

&lt;p&gt;Even after 10 years working inside large Rails codebases, here's some features that I've discovered recently working with our clients from NextLink Labs (&lt;a href="https://nextlinklabs.com" rel="noopener noreferrer"&gt;https://nextlinklabs.com&lt;/a&gt;) that make Rails faster, safer, and a lot more fun. Below are my top ten, each paired with a minimal example you can drop into any 6.1 + app (most work on 7.0–7.2).&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Strict Loading
&lt;/li&gt;
&lt;li&gt;
Asynchronous Queries
&lt;/li&gt;
&lt;li&gt;
Multi-Database Connection Switching &amp;amp; Sharding
&lt;/li&gt;
&lt;li&gt;
Delegated Types
&lt;/li&gt;
&lt;li&gt;
Active Record Encryption
&lt;/li&gt;
&lt;li&gt;
Attributes API &amp;amp; Custom Types
&lt;/li&gt;
&lt;li&gt;
Turbo-Stream Broadcasting from Models
&lt;/li&gt;
&lt;li&gt;
Built-in Rate Limiting
&lt;/li&gt;
&lt;li&gt;
One-Command Dev Containers
&lt;/li&gt;
&lt;li&gt;
Ignoring Counter Caches While Backfilling
&lt;/li&gt;
&lt;li&gt;
Default GitHub CI Workflow
&lt;/li&gt;
&lt;li&gt;
YJIT as the Default JIT Engine
&lt;/li&gt;
&lt;li&gt;
Browser Version Guard
&lt;/li&gt;
&lt;li&gt;
Out-of-the-Box PWA Files
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Strict Loading
&lt;/h2&gt;

&lt;p&gt;Raise an error the moment an association lazy-loads, catching &lt;strong&gt;N + 1&lt;/strong&gt; problems while you code rather than in production.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Article &amp;lt; ApplicationRecord
  strict_loading_by_default
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  2. Asynchronous Queries
&lt;/h2&gt;

&lt;p&gt;Off-load expensive SQL to a background pool while the request keeps executing.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;posts   = Post.published.order(created_at: :desc).load_async
authors = Author.popular.limit(10).load_async
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When you finally call &lt;code&gt;posts.each&lt;/code&gt;, the records are already waiting in memory.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Multi-Database Connection Switching &amp;amp; Sharding
&lt;/h2&gt;

&lt;p&gt;Read-replica traffic and horizontal shards are first-class citizens.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AnimalsRecord.connected_to(role: :reading) { Report.last }

TenantsRecord.connected_to(shard: :europe) do
  Invoice.create!(...)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  4. Delegated Types
&lt;/h2&gt;

&lt;p&gt;A clean alternative to both STI and polymorphic associations.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Entry &amp;lt; ApplicationRecord
  delegated_type :entryable, types: %w[Post Comment]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Entry.first.entryable&lt;/code&gt; transparently returns the concrete model with zero casting or multi-table joins.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Active Record Encryption
&lt;/h2&gt;

&lt;p&gt;Transparent, per-attribute encryption baked into Rails 7.&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
  encrypts :ssn, deterministic: true
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Rails handles key rotation, blind-index search, and log filtering—no extra gems required.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Attributes API &amp;amp; Custom Types
&lt;/h2&gt;

&lt;p&gt;Cast arbitrary data into Ruby objects without virtual-attribute hacks.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MoneyType &amp;lt; ActiveModel::Type::Integer
  def serialize(value)   = (value.to_f * 100).to_i
  def deserialize(value) = value.to_i / 100.0
end

class Product &amp;lt; ApplicationRecord
  attribute :price, MoneyType.new
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Validations, serializers, and forms treat &lt;code&gt;price&lt;/code&gt; as a float while the database stores cents.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Turbo-Stream Broadcasting from Models
&lt;/h2&gt;

&lt;p&gt;Real-time UI updates with a single callback.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Message &amp;lt; ApplicationRecord
  after_create_commit -&amp;gt; { broadcast_append_to :chat }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Every new message pushes a &lt;code&gt;&amp;lt;turbo-stream&amp;gt;&lt;/code&gt; fragment to subscribed browsers—no controller code, no JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Built-in Rate Limiting
&lt;/h2&gt;

&lt;p&gt;Rails 7.2 ships with &lt;code&gt;rate_limit&lt;/code&gt;, ending the reign of Rack-Attack.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Api::SessionsController &amp;lt; ActionController::API
  rate_limit to: 10, within: 1.minute, only: :create
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Exceeding the limit triggers an automatic &lt;strong&gt;HTTP 429&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Browser Version Guard
&lt;/h2&gt;

&lt;p&gt;Block outdated browsers via a declarative whitelist.&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;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&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;allow_browser&lt;/span&gt; &lt;span class="ss"&gt;safari: &lt;/span&gt;&lt;span class="s2"&gt;"16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;chrome: &lt;/span&gt;&lt;span class="s2"&gt;"110"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;firefox: &lt;/span&gt;&lt;span class="s2"&gt;"112"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Out-of-the-Box PWA Files
&lt;/h2&gt;

&lt;p&gt;Rails 7.2 generators include a manifest and service-worker template under /pwa, making an installable, offline-capable Progressive Web App a few edits away.&lt;/p&gt;




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

&lt;p&gt;That’s a whirlwind tour through some more advanced features that I've learned and found useful in my recent work. How many were new to you? Drop me a note—I’d love to hear about your examples of useful Rails features.&lt;/p&gt;

&lt;p&gt;If you're struggling with a legacy Rails app or looking for any kind of help with your application, feel free to send us a message here (&lt;a href="https://nextlinklabs.com/contact" rel="noopener noreferrer"&gt;https://nextlinklabs.com/contact&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;You might also find some of my other blog posts useful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextlinklabs.com/resources/insights/most-common-technical-debt-in-rails-projects" rel="noopener noreferrer"&gt;Common Types of Rails Technical Debt&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextlinklabs.com/resources/insights/six-tips-for-inheriting-a-legacy-rails-app" rel="noopener noreferrer"&gt;Six Tips For Inheriting a Legacy Rails App&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>rails</category>
      <category>learning</category>
    </item>
    <item>
      <title>Supercharging Rails: Enabling Ruby's YJIT Compiler in Production</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Mon, 22 Apr 2024 00:15:12 +0000</pubDate>
      <link>https://dev.to/colinsoleim/supercharging-rails-enabling-rubys-yjit-compiler-in-production-56o0</link>
      <guid>https://dev.to/colinsoleim/supercharging-rails-enabling-rubys-yjit-compiler-in-production-56o0</guid>
      <description>&lt;p&gt;This is a cross-post from my company blog here: &lt;a href="https://nextlinklabs.com/resources/insights/supercharging-rails-enabling-rubys-yjit-compiler-in-production"&gt;https://nextlinklabs.com/resources/insights/supercharging-rails-enabling-rubys-yjit-compiler-in-production&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In recent years, the Ruby community has eagerly awaited the introduction of the YJIT (Just-In-Time) compilation engine, a feature that promised to significantly enhance Ruby's performance by converting Ruby bytecode into machine code just before execution. For Rails applications, this means the possibility of improved response times and reduced server load, making YJIT a compelling option for production environments. This post aims to walk you through the process of enabling YJIT in your Rails application to capitalize on these performance enhancements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding YJIT
&lt;/h2&gt;

&lt;p&gt;Before we dive into the setup process, it's important to understand what the YJIT project is and how it represents a departure from Ruby's previous efforts with Just-In-Time compilers. As a method-based JIT compiler integrated into the CRuby interpreter, YJIT is designed to be more efficient and practical for real-world applications, aiming to reduce the overhead typically associated with JIT compilation. Benchmarks performed by all major companies over the last year have been promising, showcasing YJIT as a valuable asset for Rails applications looking to boost performance.&lt;/p&gt;

&lt;p&gt;For a full background, Shopify's engineering blog here provides an in-depth look at the YJIT compiler's development and the progress made by the team. The project is also open-source, and anyone curious can read the full documentation and even the source code itself on Github here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing Your Application for YJIT
&lt;/h2&gt;

&lt;p&gt;Although YJIT was made publicly available in Ruby 3.1.0, we recommend updating to Ruby version 3.2.0 and Rails version 6.0+ as both of those versions include a number of changes to the YJIT compiler.&lt;/p&gt;

&lt;p&gt;From Ruby 3.3.0 and Rails 7.1.0 onwards, YJIT will be enabled by default, simplifying the process for those able to upgrade to these versions. If your project isn't on these versions yet, we suggest prioritizing these upgrades and allowing some time for stabilization in production before activating YJIT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing With YJIT Enabled
&lt;/h2&gt;

&lt;p&gt;Because the YJIT compiler is a new and potentially dangerous technology, it's very important that you do full regression testing before deploying. To begin testing in your local environment, first ensure that your local ruby version has yjit enabled by running the following command and you'll likely see one of the two responses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Success
&amp;gt; ruby --yjit -v
ruby 3.2.2


# Error: Rust dependency is missing
&amp;gt; ruby --yjit -v
warning: Ruby was built without YJIT support. You may need to install rustc to build Ruby with YJIT.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get the dependency error for rustc, then install rust locally, uninstall your current version of ruby and re-install. An example of the commands are below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
&amp;gt; source $HOME/.cargo/env
&amp;gt; rustc --version
rustc 1.77.2 (25ef9e3d8 2024-04-09)

&amp;gt; asdf uninstall ruby 3.2.2
&amp;gt; asdf plugin-update ruby
&amp;gt; asdf install ruby 3.2.2
&amp;gt; ruby --yjit -e "p RubyVM::YJIT.enabled?"                    
true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the YJIT compiler is configured locally, run your automated test suite and perform local regression testing following your normal testing procedure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling YJIT in your Deployed Environments
&lt;/h2&gt;

&lt;p&gt;After you are confident in your regression testing, you can move to activating YJIT in your deployed environments, which can be accomplished through an ENV variable or directly within your application's code. YJIT is compatible with popular Ruby servers like Puma, Unicorn, and Webrick. Although there has not been extensive testing with servers such as Falcon or Thin, YJIT is expected to work seamlessly across different environments. Encountering issues with any server should prompt a bug report to help ensure YJIT's broad compatibility.&lt;/p&gt;

&lt;p&gt;For those preferring an environment variable setup, you can enable YJIT in your production environment with the following configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In production server configurations
export RUBYOPT="--yjit"

# In Dockerfile
ENV RUBYOPT="--yjit"

# In binstubs, e.g. bin/rails
RUBYOPT="--yjit"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruby 3.3.0 users have an additional option, thanks to YJIT's paused-by-default state, allowing for initialization within the application. More information on this feature can be found on GitHub. An initializer might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In production server configurations
if defined?(RubyVM::YJIT) &amp;amp;&amp;amp; RubyVM::YJIT.respond_to?(:enable)
  RubyVM::YJIT.enable
else
  puts "YJIT is not enabled"
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment and Monitoring
&lt;/h2&gt;

&lt;p&gt;Once YJIT is enabled, deploy your application as you normally would, but pay close attention to performance changes. Utilize performance monitoring tools to track improvements or identify potential issues post-deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anticipated Performance Gains
&lt;/h2&gt;

&lt;p&gt;Implementing YJIT may alter memory usage, affecting your server's process and thread configuration. While YJIT can significantly enhance performance, especially for CPU-intensive applications with adequate memory, its effectiveness can vary. It's currently supported on x86 architecture for macOS and Linux, with notable speed increases reported in benchmarks.&lt;/p&gt;

&lt;p&gt;While development environments may not see dramatic benefits due to Rails' code reloading behavior, YJIT still holds potential for applications with heavily used library methods. Testing and experimentation are key to evaluating YJIT's impact on your development process.&lt;/p&gt;

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

&lt;p&gt;YJIT marks a significant advancement in Ruby's development, offering Rails applications a path to improved performance. By following this guide to enable YJIT, you could see faster response times and a more fluid user experience. With the Ruby community's ongoing efforts to refine YJIT, keeping abreast of new developments will ensure your application benefits from the latest performance optimizations. This guide aims to equip you with the knowledge to leverage YJIT's advantages, fostering a more efficient and responsive production environment.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>My Rubocop Configuration for a Successful Rails Project</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Tue, 09 Feb 2021 16:08:14 +0000</pubDate>
      <link>https://dev.to/colinsoleim/my-rubocop-configuration-for-a-successful-rails-project-3b78</link>
      <guid>https://dev.to/colinsoleim/my-rubocop-configuration-for-a-successful-rails-project-3b78</guid>
      <description>&lt;p&gt;This article was originally posted on our &lt;a href="https://nextlinklabs.com/insights/our-rubocop-configuration-for-rails-development-projects"&gt;company blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;After over 8 years in development, the Ruby linting gem Rubocop has finally released version 1.0 and with it a host of new features, style configurations, and most importantly a much higher degree of stability. Many developers in the Ruby community have depended on Rubocop for years, and we are no exception. &lt;/p&gt;

&lt;p&gt;If you’re unfamiliar with Rubocop, don’t worry -- it’s pretty simple to explain. Rubocop is an extremely flexible Ruby code style checker and formatter that can identify and in many cases fix problems in your code. Learn more about it &lt;a href="https://rubocop.org/"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We use Rubocop on all of our Rails &lt;a href="https://dev.to/services/custom-software-development"&gt;custom software development projects&lt;/a&gt; for a number of reasons which we'll outline below. How Rubocop is configured is largely up to the developer but we’ve found a few rules to follow that align with our goals as a technology company. To that end, we’re offering our configuration scheme below along with our rules of thumb for rubocop. &lt;/p&gt;

&lt;p&gt;(If you'd just like to jump to our recommended .rubocop.yml configuration file, &lt;a href="https://github.com/colinsoleim/react-on-rails-template/blob/main/.rubocop.yml"&gt;here's a link to the full file.&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Enforce Good Object-Oriented Design
&lt;/h2&gt;

&lt;p&gt;First and foremost, we use configuration options in Rubocop to push us towards good object-oriented design decisions. We're big fans of Sandi Metz and her &lt;a href="https://thoughtbot.com/blog/sandi-metz-rules-for-developers"&gt;4 Rules for Developers&lt;/a&gt;. To summarize the linked blog post, the four rules are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep all classes and files to 100 lines or less.&lt;/li&gt;
&lt;li&gt;Keep all methods to 5 lines or less.&lt;/li&gt;
&lt;li&gt;Keep all methods to 4 parameters or less.&lt;/li&gt;
&lt;li&gt;Only instantiate one instance variable in each controller method.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We use the Metrics options in Rubocop to enforce these rules across our entire app.&lt;/p&gt;

&lt;p&gt;Unfortunately, we haven't been able to find any configuration to alert us if a controller is only using one instance variable, but the combination of the &lt;code&gt;Metrics/PerceivedComplexity&lt;/code&gt;, &lt;code&gt;Metrics/AbcSize&lt;/code&gt;, and &lt;code&gt;Metrics/CyclomaticComplexity&lt;/code&gt; give us a good idea if any controller methods are getting too complex.&lt;/p&gt;

&lt;p&gt;For the other 3 rules, we use the following Metrics configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Metrics Cops

Metrics/ClassLength:
  Description: 'Avoid classes longer than 100 lines of code.'
  Max: 100
  Enabled: true

Metrics/ModuleLength:
  Description: 'Avoid modules longer than 100 lines of code.'
  Max: 100
  Enabled: true

Metrics/ParameterLists:
  Description: 'Pass no more than four parameters into a method.'
  Max: 4
  Enabled: true

Metrics/MethodLength:
  Description: 'Avoid methods longer than 5 lines of code.'
  StyleGuide: '&amp;lt;https://github.com/bbatsov/ruby-style-guide#short-methods&amp;gt;'
  Max: 5
  Enabled: true

Metrics/BlockLength:
  CountComments: false
  Max: 5
  IgnoredMethods:
    - context
    - describe
    - it
    - shared_examples
    - shared_examples_for
    - namespace
    - draw
    - configure
    - group
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Uniform Style Throughout the App
&lt;/h2&gt;

&lt;p&gt;The most obvious reason to use an automated linting tool is to eliminate all style questions from code reviews. In our experience, these kinds of conversations often lead to bikeshedding and can distract from reviewing the implementation details which should be the main point of code review.&lt;/p&gt;

&lt;p&gt;Our list of style preferences was built up gradually as team members found things they disagreed with in the default options. Whenever developers feel like we should make a change to these styles, they open up a Pull Request to our main style guide which is not attached to any project and there everyone can weigh in with their opinions. &lt;/p&gt;

&lt;p&gt;This process allows us to have a full conversation without holding up the deployment of any features or bug fixes.&lt;br&gt;
We recommend using the same process to create your own configurations for Layout and Style. &lt;/p&gt;
&lt;h2&gt;
  
  
  Override Warnings With &lt;code&gt;rubocop_todo.yml&lt;/code&gt; File
&lt;/h2&gt;

&lt;p&gt;As a general rule, we never change the rubocop.yml configuration file inside a specific client project unless we've merged a pull request to our generic style guide. However, there are times when we break our own rules temporarily and for this we use a &lt;code&gt;.rubocop_todo.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;This file lets you skip a specific cop for an individual file and is a perfect tool if you need to, for example, introduce a method longer than five lines for a hotfix or an urgent feature. All you have to do is add the line &lt;code&gt;inherit_from: .rubocop_todo.yml&lt;/code&gt; to the top of your project's rubocop config file.&lt;/p&gt;

&lt;p&gt;Using a todo file in this way gives us an itemized list of any technical debt we've accrued and ensures that we don't ease up on any of our rules in the &lt;code&gt;.rubocop.yml&lt;/code&gt; file itself and then forget to tighten them back up after we refactor.&lt;/p&gt;
&lt;h2&gt;
  
  
  Other Rubocop Plugins
&lt;/h2&gt;

&lt;p&gt;Rubocop allows you to import custom plugins for customized cops, and we use 3 of these plugins in all of our Rails projects. These are &lt;a href="https://github.com/rubocop-hq/rubocop-performance"&gt;rubocop-performance&lt;/a&gt;, &lt;a href="https://github.com/rubocop-hq/rubocop-rails"&gt;rubocop-rails&lt;/a&gt;, and &lt;a href="https://github.com/rubocop-hq/rubocop-rspec"&gt;rubocop-rspec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We agree with almost all of the default settings in these plugins and they provide a more granular degree of static analysis just by requiring them at the top of our rubocop config file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require:
  - rubocop-performance
  - rubocop-rails
  - rubocop-rspec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Our Ignored Folders
&lt;/h2&gt;

&lt;p&gt;We've seen a wide variety of recommendations on what folders should be ignored by Rubocop. We generally only find Rubocop warnings useful for files inside the &lt;code&gt;app/&lt;/code&gt; folder, the &lt;code&gt;lib/&lt;/code&gt; folder, the &lt;code&gt;spec/&lt;/code&gt; folder, and some files inside the &lt;code&gt;config/&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Everything we write in the &lt;code&gt;app/&lt;/code&gt; folder should be checked by Rubocop, it doesn't seem like there's much disagreement there.&lt;/p&gt;

&lt;p&gt;Some developers do exclude their tests folder from Rubocop linting, but we view our tests as core to the documentation of our projects, and therefore we want the tests to be as readable as possible. The structure of code in test files can be a little different than code in a model or service object, so we do have some linting rules that skip the spec folder, for example we allow blocks longer than 5 lines in that folder.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;config/&lt;/code&gt; and &lt;code&gt;lib/&lt;/code&gt;, we tend to have a number of custom initializers and rake tasks in those folders respectively that need to be formatted. However, many files in the config folder are auto-generated by gems or by Rails itself, and we do skip running Rubocop on those files to keep them identical to the gem or library documentation for easier cross-referencing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Prettier with Rubocop
&lt;/h2&gt;

&lt;p&gt;Rubocop has a very nice auto-correct feature to automatically fix many of the warnings it gives, but we've noticed in the past that with line length issues specifically the auto-corrected files can be misformatted. For that reason, we use the &lt;a href="https://github.com/prettier/plugin-ruby"&gt;Ruby plugin for Prettier&lt;/a&gt; to correct line length.&lt;/p&gt;

&lt;p&gt;By default, prettier reformats any line over 80 characters in length, but we've agreed to increase that limit to 120 characters on our projects. We were especially happy to see that even &lt;a href="https://lkml.org/lkml/2020/5/29/1038"&gt;Linus Torvalds&lt;/a&gt; agrees that the 80 character limit is a bit outdated with modern monitors and IDEs.&lt;/p&gt;

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

&lt;p&gt;Rubocop is an incredibly valuable tool we have in the Ruby community. With some basic configuration, it can provide a lot more than simple style warnings, and we recommend everyone use it on their Rails projects. &lt;br&gt;
Here is the final version of our rubocop configuration file combining all the items we discussed above: &lt;a href="https://github.com/colinsoleim/react-on-rails-template/blob/main/.rubocop.yml"&gt;https://github.com/colinsoleim/react-on-rails-template/blob/main/.rubocop.yml&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>8 Common Types of Technical Debt with Rails Applications
</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Sun, 17 Jan 2021 22:02:23 +0000</pubDate>
      <link>https://dev.to/colinsoleim/8-common-types-of-technical-debt-in-rails-6ca</link>
      <guid>https://dev.to/colinsoleim/8-common-types-of-technical-debt-in-rails-6ca</guid>
      <description>&lt;p&gt;This article was originally posted on &lt;a href="https://nextlinklabs.com/insights/most-common-technical-debt-in-rails-projects"&gt;our blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The majority of the Rails &lt;a href="https://nextlinklabs.com/services/custom-software-development"&gt;custom software development&lt;/a&gt; work we do at NextLink Labs deals with rehabilitating older projects that are overwhelmed with technical debt from years of development without refactoring.&lt;/p&gt;

&lt;p&gt;The software problems in these websites are never introduced maliciously. Instead, these problems tend to build up gradually over months and years after many rushed deadlines, strict client demands that don't allow for refactoring, and inexperienced Rails developers trying their best but getting overwhelmed by "&lt;em&gt;Rails magic&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;After working on many of these kinds of projects, we've identified a number of categories for these kinds of problems which we outline below with possible fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. No Tests
&lt;/h2&gt;

&lt;p&gt;A lack of automated tests is by far the most common problem with Rails projects.&lt;/p&gt;

&lt;p&gt;Typically this happens when a developer starts a new project and is writing all the code themselves. Because they're writing everything, they never feel a need to "waste time" writing automated tests.&lt;/p&gt;

&lt;p&gt;Inevitably, the project grows large enough that manually testing features in the browser becomes a pain, and it becomes obvious a test suite is needed. However, by that point the amount of tests that would be needed for adequate coverage is overwhelming, and so the tests never get written.&lt;/p&gt;

&lt;p&gt;The most important step to start fixing this problem is to write just one "sanity" test that checks the most basic pieces of your app. As soon as you have one test on a project, you have a basic testing foundation. Then when you have downtime on a project or when you're adding new features later on, you can slowly add more tests using that basic foundation you've set up.&lt;/p&gt;

&lt;p&gt;Although we don't necessarily recommend all teams follow a strict Test-Driven Development (especially when a team is inexperienced with Rails testing), we do recommend at least writing a few high level integration tests before building any new feature. This ensures that even in the worst case scenario, you have at least one test that will check each feature's behavior is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Slow Test Suites
&lt;/h2&gt;

&lt;p&gt;Developers that are new to testing will often swing the opposite direction after learning about the peace of mind a good test suite brings, and they will write dozens of redundant tests. This is an inevitable part of learning how to test Rails applications, and it's certainly a much better problem to have than too few tests. However, having a test suite that takes 15 or more minutes to run can throw off a team's momentum.&lt;/p&gt;

&lt;p&gt;A slow test suite is most often caused by either an over-dependence on feature tests that use tools like Caybara to check the front-end or by having too much build up and tear down in your tests themselves.&lt;/p&gt;

&lt;p&gt;To solve the problem of too many feature tests, first make sure you are trusting your unit tests and controller tests. This is a common problem where newer developers only trust a test that goes through a full feature the way a human would.&lt;/p&gt;

&lt;p&gt;After you've removed any of these unit tests that are just disguising themselves as feature tests, consider combining multiple feature tests together. By their nature, feature tests require a lot of build up time to fill your database with the necessary records, so just combining 3-4 related tests into one longer test can save a lot of time.&lt;/p&gt;

&lt;p&gt;For example, rather than having separate tests for searching, filtering, and sorting records, we create a single long test where a user creates a record, filters for that record, then deletes that record, etc. In this way, we limit each feature to one happy path test and several error path tests, and keep our Capybara feature test count very low compared to unit tests and controller tests.&lt;/p&gt;

&lt;p&gt;We also make extensive use of RSpec's stubbing capabilities and use dependency injection wherever possible to keep build up and tear down speed fast. Dependency injection is a paradigm in software that states a class should mention no other classes by name and instead they should be passed in as parameters when instantiating an object. This allows us to pass in stubbed RSpec objects which are extremely fast and allow us to test the behavior we've isolated.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Fat Controllers
&lt;/h2&gt;

&lt;p&gt;Creating "Fat Controllers" is an extremely common mistake for developers who are new to Rails. It's natural to want to keep your code all in one place, and it can take a while before you start to see the problems with having 20 or more lines of application logic inside controller methods.&lt;/p&gt;

&lt;p&gt;Eventually, putting everything inside of a controller leads to unreadably long controller actions with many different instance variables. Because of how Rails controllers and views interact, it can be hard to tell if a specific instance variable is still being used when you have 5-10 variables declared inside a controller.&lt;/p&gt;

&lt;p&gt;For this reason, we keep our controller actions to 5 lines or fewer and we only instantiate 1 instance variable in each controller action. To do this, we often create custom classes for a specific controller action, for example, an EventFinder class for a meetup style application or a Dashboard object for an application that has several different graphs or charts on its homepage. We find these custom classes much easier to deal with and much easier to test without going through the front-end of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Fat Models
&lt;/h2&gt;

&lt;p&gt;The most common solution to the "Fat Controller" problem is to create "Fat Models". We see many intermediate Rails developers follow the "Skinny Controller, Fat Model" paradigm, but this can lead to problems as well, especially if those models are inheriting from ActiveRecord and are not standalone Ruby classes.&lt;/p&gt;

&lt;p&gt;When you shove all of your logic into ActiveRecord models, you start to get giant files that are over 200-300 lines long and unreadably complex. Your controllers will look much simpler, but the complexity is just one layer deeper. All your business logic is still being organized by your database tables and is being mixed in with all your persistence logic.&lt;/p&gt;

&lt;p&gt;We advocate for using standalone Ruby classes, often referred to as service objects, for all of your application's business logic. These classes do not inherit from ActiveRecord and are kept in a separate folder, e.g. &lt;code&gt;/app/services&lt;/code&gt;. This allows you to keep your model files small and strictly related to the structure of your data, for example &lt;code&gt;has_many&lt;/code&gt; and &lt;code&gt;belongs_to&lt;/code&gt; statements and any kinds of validation logic that may be needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Using ActiveRecord Callbacks
&lt;/h2&gt;

&lt;p&gt;ActiveRecord callbacks are a common tool used by Rails developers, but we've found they cause more headaches than any other aspect of "Rails magic" when we take on older projects. Callbacks like &lt;code&gt;after_save&lt;/code&gt;, &lt;code&gt;before_action&lt;/code&gt;, etc. are often tempting to use because they can hide complexity and make code look appealing, but they also hide large amounts of implicit behavior that prevents new developers coming on to a project from understanding the application's flow and developing a mental model for how the codebase works.&lt;/p&gt;

&lt;p&gt;We've seen countless bugs over the years from ActiveRecord callbacks, and at this point, we tend to avoid them at all costs. When we find them in client projects, we typically try and refactor them into explicit behavior whenever possible.&lt;/p&gt;

&lt;p&gt;Besides just hiding complexity, another problem with callbacks like &lt;code&gt;before_action&lt;/code&gt; specifically, is that they're used by developers to DRY up code prematurely. Often times, code that is inside a &lt;code&gt;before_action&lt;/code&gt; callback will need to be changed slightly for each controller action as a feature is expanded. This turns the &lt;code&gt;before_action&lt;/code&gt; method from a simple 1 line ActiveRecord query into a 20 line conditional that is extremely hard to parse.&lt;/p&gt;

&lt;p&gt;We're much more comfortable repeating the query inside each controller action, so if changes do need to be made to one specific controller action, there's no need for any messy conditionals.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Out Of Date README File
&lt;/h2&gt;

&lt;p&gt;As a project evolves and adds dependencies and setup, it's very easy for a README to become out of date. In our READMEs, we include information on how to setup the app, how to run tests and linters, how to deploy to staging and production, and information on any other scripts that need to be run regularly.&lt;/p&gt;

&lt;p&gt;Ideally, all of this information should be updated when any of these processes change, but this can sometimes be forgotten. To ensure everything in the README is correct, whenever a new developer starts on one of our projects, we have them try to set up the project without interacting with other team members, only using the README. If they run into any problems or need to ask questions to a developer already on the project, we immediately update the README, and let them continue through the process until we confirm everything is correct. This gives us an easy way to check the documentation at least every few months.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Not Using View Partials
&lt;/h2&gt;

&lt;p&gt;We follow the 100 line file limit as a general rule of thumb in all of our projects, and one place where file length can quickly spiral out of control is with HTML views. All it takes is a few conditionals and a few sets of nested bootstrap divs, and a view becomes hard to understand without spending an hour or more doing line by line analysis.&lt;/p&gt;

&lt;p&gt;To counter this, we use view partials whenever possible to logically break up long view files into easily understandable pieces. Sometimes developers new to Rails are hesitant to create views outside of the standard REST actions (show, index, new, etc.), but we've found separating views into custom folders and files makes our HTML much more understandable.&lt;/p&gt;

&lt;p&gt;One important thing to keep in mind when using view partials is to never depend on a global instance variable inside the partial and always pass variables you need into the partial's render statement explicitly. Down the road, if you decide to reuse a partial inside a separate view, depending on an instance variable from a controller method can lead to both bugs from a missing variable or bad controller design by adding extra instance variables to a controller method.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Complicating Your Code with Unnecessary Gems
&lt;/h2&gt;

&lt;p&gt;A final anti-pattern I've noticed with new developers is a tendency to use gems instead of creating their own classes and database tables. I encountered an example of this recently where a junior developer was building a messaging feature between users. Their first instinct was to look for gems to implement this feature and they found the &lt;a href="https://github.com/mailboxer/mailboxer"&gt;mailboxer gem&lt;/a&gt;. Mailboxer is a fairly complex gem which will build a full mailbox system (4 database tables with 10+ fields each) with features such as inbox, outbox, read receipts, etc.&lt;/p&gt;

&lt;p&gt;These extra features were all overkill for the project we were building and would have added a ton of extra complexity to our small messaging feature. After talking through the problem together, we agreed on taking a simpler approach where we created our own Messages database table which had a sender and receiver and a single content field to store the message itself.&lt;/p&gt;

&lt;p&gt;The junior developer mentioned not trusting their own ability to create a new database table, which is a common theme with newer developers. Adding a new gem to the Gemfile and running a generation script can seem like it's always a better option when you're inexperienced, but even if the gem is written by a more experienced developer, gems can introduce lots of unnecessary complexity which weigh down your app over time.&lt;/p&gt;

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

&lt;p&gt;Technical debt is a growing concern in custom software development, especially for those that are taking over legacy projects. If that sounds familiar and you need some help, read our guide for &lt;a href="https://nextlinklabs.com/insights/six-tips-for-inheriting-a-legacy-rails-app"&gt;successfully inheriting a legacy rails project&lt;/a&gt; here. If you need help getting started with a &lt;a href="https://nextlinklabs.com/services/custom-software-development"&gt;custom software development project&lt;/a&gt; or need help navigating the &lt;a href="https://nextlinklabs.com/services/devops-consulting-services"&gt;digital transformation&lt;/a&gt;, contact us.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>6 Steps to Take When Inheriting Legacy Rails Apps</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Tue, 01 Dec 2020 14:26:09 +0000</pubDate>
      <link>https://dev.to/colinsoleim/6-things-to-do-when-inheriting-legacy-rails-apps-443g</link>
      <guid>https://dev.to/colinsoleim/6-things-to-do-when-inheriting-legacy-rails-apps-443g</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I started a new job back in June and my first project was taking over and making updates to a big legacy Rails app. Taking the project over was pretty much a worst-case scenario because the project had no tests and nobody who had built the website was still contactable.&lt;/p&gt;

&lt;p&gt;Luckily I've been working with Rails for 6 years, and most of the decisions on this project ended up being the Rails standard, so I was able to setup the project, add some tests, and figure out deployments to staging/production.&lt;/p&gt;

&lt;p&gt;Along the way I kept notes of my process, and wrote this blog post which gives the 6 steps I take when starting a project like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextlinklabs.com/insights/six-tips-for-inheriting-a-legacy-rails-app"&gt;https://nextlinklabs.com/insights/six-tips-for-inheriting-a-legacy-rails-app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear any feedback on the blog post! Also, have any of you had a situation like this where you had to take over an existing project after the original developers have disappeared?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rails</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A Detailed Breakdown of My 8 Year Journey to Senior Engineer</title>
      <dc:creator>Colin Soleim</dc:creator>
      <pubDate>Wed, 17 Jun 2020 01:55:03 +0000</pubDate>
      <link>https://dev.to/colinsoleim/a-detailed-breakdown-of-my-journey-to-senior-engineer-2i2j</link>
      <guid>https://dev.to/colinsoleim/a-detailed-breakdown-of-my-journey-to-senior-engineer-2i2j</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;When I was teaching myself to code, I constantly searched for detailed, step-by-step stories of other people's journeys from beginner coding classes to full-time engineering jobs. Last week, I accepted an offer as a Senior Software Developer. Following the advice to write about what you wished existed, I wanted to share my own eight-year path from my first codeacademy.com class to landing this role.&lt;/p&gt;

&lt;p&gt;I'm not sure how broadly applicable this will be, so instead of offering generalized advice, I'll simply present my journey as one data point of what's possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beginning/College (2012-2014)
&lt;/h2&gt;

&lt;p&gt;I began coding with Codecademy, learning HTML, CSS, JavaScript, and Ruby.&lt;/p&gt;

&lt;p&gt;I tried creating a Twitter bot to automate tweets, but failed for numerous reasons. However, researching Twitter's API led me to Michael Hartl's Rails Tutorial. I eagerly read the first five chapters before getting excited and returning to my personal projects.&lt;/p&gt;

&lt;p&gt;My first Rails project was a site listing daily drink specials in my hometown. This failed quickly because I didn't understand databases and tried hardcoding each special—tedious and unsustainable.&lt;/p&gt;

&lt;p&gt;In college, I took a basic Java course (Comp Sci 101). My final project was a Rails app embedding jsfiddle demos of simple JavaScript games. It looked terrible, had no database, but I managed to deploy it to Heroku and even got an A.&lt;/p&gt;

&lt;p&gt;I also created a personal Rails website without a database, deploying it to Heroku and connecting it to a Namecheap domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  After College Work
&lt;/h2&gt;

&lt;p&gt;By this point, I'd deployed a few basic HTML-style websites to Heroku and was overly confident at 22. I applied to a couple of jobs and interviewed at two startups. One was a full-time role, and the other an internship. The full-time job flew me in for an interview, quickly revealing I lacked crucial skills like ActiveRecord, MVC architecture, and CSS frameworks. But they generously paid me $250 for eight hours of work—my first earnings from programming.&lt;/p&gt;

&lt;p&gt;The internship interview was simpler, conducted by a non-technical founder. My misplaced confidence helped—I claimed comfort with databases, Rails/Django, and JavaScript, which was true to my understanding at the time. It wasn't until starting the internship that I recognized how little I actually knew.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internship Program (2014)
&lt;/h2&gt;

&lt;p&gt;My internship began with a struggle: I failed miserably at writing Ember tests and experienced a small breakdown after my second day. This humbling moment marked the turning point of my career.&lt;/p&gt;

&lt;p&gt;Thankfully, a senior Rails engineer took me under his wing, pairing with me for a few days until I could handle smaller tasks independently. For the rest of the summer, I remember coding relentlessly—around 80 hours a week—driven by enthusiasm, anxiety, and a strong desire to prove myself.&lt;/p&gt;

&lt;p&gt;During this internship, I contributed my first open-source pull request to a Ruby gem that queried the SEC database. It was a small and admittedly messy fix, but I was incredibly proud at the time (&lt;a href="https://github.com/tyrauber/sec_query/commit/004d9c494bf72d6b3fe50a1d4bdfaf7a0fba9714" rel="noopener noreferrer"&gt;https://github.com/tyrauber/sec_query/commit/004d9c494bf72d6b3fe50a1d4bdfaf7a0fba9714&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Entering the Job Market
&lt;/h2&gt;

&lt;p&gt;By the end of the internship, I had a foundational grasp of web development: databases, MVC architecture, AJAX, common Rails gems, HTML/CSS, and JavaScript.&lt;/p&gt;

&lt;p&gt;At a launch event, I met someone who needed a website. Over the next month, I built a Rails site using Bootstrap. The project went fine, though behind the scenes, the code was messy. Nonetheless, the client was satisfied, and I earned around $3000—an eye-opening sum at the time, showing me the value developers could create.&lt;/p&gt;

&lt;p&gt;Shortly after, a consulting company from my internship approached me with a contract offer (hourly initially, then full-time fixed hours).&lt;/p&gt;

&lt;h2&gt;
  
  
  Consulting Company Contractor (2015-2019)
&lt;/h2&gt;

&lt;p&gt;My first project was a Rails app for the Shopify App Store. The site launched successfully, but looking back, the code had major issues—huge controllers, enormous jQuery files, and other poor practices.&lt;/p&gt;

&lt;p&gt;My next major project was an eight-month Rails app—an event marketplace for entertainers. It was my first high-traffic production site, and performance issues quickly surfaced, highlighting flaws in my coding style.&lt;/p&gt;

&lt;p&gt;While addressing these issues, I discovered Sandi Metz and Thoughtbot, who taught me about testing and good object-oriented design. Refactoring my previous projects using these new skills drastically reduced my daily stress.&lt;/p&gt;

&lt;p&gt;My final large project at this company was an 18-month engagement with an e-commerce startup. I managed their custom Shopify theme designs and built several private apps, serving as a jack-of-all-trades developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Post Contractor Position (2019-2020)
&lt;/h2&gt;

&lt;p&gt;After four years of entirely remote work and often being the sole developer on projects, I decided to seek roles with in-person collaboration opportunities. I first took a few months off from coding, then gradually returned through contributing to Ruby for Good, building Rails sites for nonprofits.&lt;/p&gt;

&lt;p&gt;When I actively began job hunting, I sent out 20-30 resumes within a week, experienced two stressful weeks of silence, then received multiple interview invitations simultaneously. Eventually, I accepted an offer from a consulting company that provides custom software and Devops solutions to a small portfolio of clients.&lt;/p&gt;

&lt;p&gt;That's been my journey so far. I hope this is helpful to anyone starting or in the middle of their web development career. Feel free to reach out on dev.to or email—I enjoy giving advice and meeting for coffee if you're in Pittsburgh.&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
