<?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: Leonid Svyatov</title>
    <description>The latest articles on DEV Community by Leonid Svyatov (@svyatov).</description>
    <link>https://dev.to/svyatov</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%2F122709%2F4d89b6fb-d4ad-4af4-9c12-8cb53789179c.jpeg</url>
      <title>DEV Community: Leonid Svyatov</title>
      <link>https://dev.to/svyatov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/svyatov"/>
    <language>en</language>
    <item>
      <title>The complete guide to `rails new` in Rails 8.1</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Tue, 03 Mar 2026 10:23:12 +0000</pubDate>
      <link>https://dev.to/svyatov/the-complete-guide-to-rails-new-in-rails-81-346c</link>
      <guid>https://dev.to/svyatov/the-complete-guide-to-rails-new-in-rails-81-346c</guid>
      <description>&lt;p&gt;&lt;code&gt;rails new --help&lt;/code&gt; prints 30+ options. Most tutorials stop at &lt;code&gt;rails new myapp -d postgresql&lt;/code&gt; and move on. This post covers every Rails 8.1 option - what it does, when to use it, and what most people pick.&lt;/p&gt;

&lt;h2&gt;
  
  
  App Mode
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--api&lt;/code&gt;&lt;/strong&gt; - Strips views, cookies, sessions, asset pipeline, &lt;a href="https://hotwired.dev/" rel="noopener noreferrer"&gt;Hotwire&lt;/a&gt;, CSS, and JavaScript. Use for pure JSON or GraphQL backends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--minimal&lt;/code&gt;&lt;/strong&gt; - Generates the smallest possible app. Skips Action Mailer, Action Mailbox, Action Text, Active Job, Active Storage, Action Cable, Hotwire, &lt;a href="https://github.com/rails/jbuilder" rel="noopener noreferrer"&gt;Jbuilder&lt;/a&gt;, tests, system tests, &lt;a href="https://kamal-deploy.org/" rel="noopener noreferrer"&gt;Kamal&lt;/a&gt;, &lt;a href="https://github.com/basecamp/thruster" rel="noopener noreferrer"&gt;Thruster&lt;/a&gt;, Solid, and &lt;a href="https://github.com/Shopify/bootsnap" rel="noopener noreferrer"&gt;Bootsnap&lt;/a&gt;. A good starting point when you want to add only what you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database (&lt;code&gt;--database=X&lt;/code&gt;)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Adapter&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;a href="https://www.sqlite.org/" rel="noopener noreferrer"&gt;sqlite3&lt;/a&gt;&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;Zero setup, no server, works with Solid stack. &lt;a href="https://37signals.com/" rel="noopener noreferrer"&gt;37signals&lt;/a&gt; runs &lt;a href="https://once.com/" rel="noopener noreferrer"&gt;ONCE&lt;/a&gt; products on it in production.&lt;/td&gt;
&lt;td&gt;Single-writer, no multi-server scaling.&lt;/td&gt;
&lt;td&gt;Solo devs, prototypes, single-server apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;postgresql&lt;/a&gt;&lt;/strong&gt; ⭐&lt;/td&gt;
&lt;td&gt;Full-featured (JSONB, arrays, full-text search), every PaaS supports it, best managed DB options.&lt;/td&gt;
&lt;td&gt;Requires a running server.&lt;/td&gt;
&lt;td&gt;Most production apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;mysql&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Widely deployed, mature.&lt;/td&gt;
&lt;td&gt;No native arrays, JSON can't be indexed directly (unlike PostgreSQL's JSONB).&lt;/td&gt;
&lt;td&gt;Existing MySQL infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://github.com/trilogy-libraries/trilogy" rel="noopener noreferrer"&gt;trilogy&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Modern MySQL client by GitHub, no C library dependency, simpler install. GitHub &amp;amp; Shopify use it in production.&lt;/td&gt;
&lt;td&gt;Newer, smaller ecosystem.&lt;/td&gt;
&lt;td&gt;New MySQL projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://mariadb.org/" rel="noopener noreferrer"&gt;mariadb&lt;/a&gt;-mysql&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;For MariaDB specifically with &lt;a href="https://github.com/brianmario/mysql2" rel="noopener noreferrer"&gt;mysql2&lt;/a&gt; adapter.&lt;/td&gt;
&lt;td&gt;Same as mysql.&lt;/td&gt;
&lt;td&gt;Existing MariaDB setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;mariadb-trilogy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;For MariaDB specifically with Trilogy adapter.&lt;/td&gt;
&lt;td&gt;Same as trilogy.&lt;/td&gt;
&lt;td&gt;New MariaDB projects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;PostgreSQL is the most common choice. When in doubt, pick it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-active-record&lt;/code&gt; / &lt;code&gt;-O&lt;/code&gt;&lt;/strong&gt; - Drops the ORM entirely. Cascading effect: also skips database, Action Mailbox, Action Text, and Active Storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JavaScript (&lt;code&gt;--javascript=X&lt;/code&gt; / &lt;code&gt;-j&lt;/code&gt;)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;a href="https://github.com/rails/importmap-rails" rel="noopener noreferrer"&gt;importmap&lt;/a&gt;&lt;/strong&gt; (default) ⭐&lt;/td&gt;
&lt;td&gt;No Node.js, no build step, browser-native ES modules, HTTP/2 parallel downloads.&lt;/td&gt;
&lt;td&gt;No tree-shaking, no TypeScript/JSX transpilation.&lt;/td&gt;
&lt;td&gt;Standard Rails + Hotwire apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extremely fast (Go-based), handles TypeScript/JSX, mature.&lt;/td&gt;
&lt;td&gt;Requires Node.js.&lt;/td&gt;
&lt;td&gt;Apps needing a bundler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;bun&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1.75x faster than esbuild, doubles as package manager + bundler.&lt;/td&gt;
&lt;td&gt;Newer, smaller ecosystem than esbuild.&lt;/td&gt;
&lt;td&gt;Speed-first, Bun ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;webpack&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-featured, huge plugin ecosystem.&lt;/td&gt;
&lt;td&gt;Slow, complex config, legacy choice.&lt;/td&gt;
&lt;td&gt;Not recommended for new projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://rollupjs.org/" rel="noopener noreferrer"&gt;rollup&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good for libraries, ES module focused.&lt;/td&gt;
&lt;td&gt;Niche in Rails context.&lt;/td&gt;
&lt;td&gt;Not recommended for new projects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Importmap is the Rails default for a reason - it eliminates Node.js from your stack entirely. Reach for esbuild or bun only when you need TypeScript, JSX, or tree-shaking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-javascript&lt;/code&gt; / &lt;code&gt;-J&lt;/code&gt;&lt;/strong&gt; - No JS setup at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS (&lt;code&gt;--css=X&lt;/code&gt; / &lt;code&gt;-c&lt;/code&gt;)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;(none)&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;No dependencies, write plain CSS.&lt;/td&gt;
&lt;td&gt;No utilities or components.&lt;/td&gt;
&lt;td&gt;Minimal apps, custom design systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;tailwind&lt;/a&gt;&lt;/strong&gt; ⭐&lt;/td&gt;
&lt;td&gt;Rails-blessed (&lt;a href="https://github.com/rails/tailwindcss-rails" rel="noopener noreferrer"&gt;&lt;code&gt;tailwindcss-rails&lt;/code&gt;&lt;/a&gt; gem), no Node.js required, v4 is 5x faster with CSS-first config.&lt;/td&gt;
&lt;td&gt;Verbose HTML classes, learning curve.&lt;/td&gt;
&lt;td&gt;Most new Rails apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;bootstrap&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pre-built components, familiar to most devs.&lt;/td&gt;
&lt;td&gt;Requires Node.js (via &lt;a href="https://github.com/rails/cssbundling-rails" rel="noopener noreferrer"&gt;&lt;code&gt;cssbundling-rails&lt;/code&gt;&lt;/a&gt;), heavier.&lt;/td&gt;
&lt;td&gt;Apps needing ready-made UI components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://bulma.io/" rel="noopener noreferrer"&gt;bulma&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CSS-only (no JS), clean modern design.&lt;/td&gt;
&lt;td&gt;Requires Node.js via &lt;code&gt;cssbundling-rails&lt;/code&gt;, smaller community.&lt;/td&gt;
&lt;td&gt;Lightweight component needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;postcss&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Plugin-based CSS transforms, flexible.&lt;/td&gt;
&lt;td&gt;Requires Node.js, config overhead.&lt;/td&gt;
&lt;td&gt;Custom CSS toolchains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;sass&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Variables, nesting, mixins, mature.&lt;/td&gt;
&lt;td&gt;Requires Node.js (&lt;a href="https://github.com/rails/propshaft" rel="noopener noreferrer"&gt;Propshaft&lt;/a&gt; doesn't compile Sass).&lt;/td&gt;
&lt;td&gt;Teams already using Sass&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No CSS framework is included by default. Tailwind is the most popular choice for new Rails apps - the &lt;code&gt;tailwindcss-rails&lt;/code&gt; gem runs standalone, no Node.js required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asset Pipeline (&lt;code&gt;--asset-pipeline=X&lt;/code&gt;)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pipeline&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;a href="https://github.com/rails/propshaft" rel="noopener noreferrer"&gt;propshaft&lt;/a&gt;&lt;/strong&gt; (default) ⭐&lt;/td&gt;
&lt;td&gt;Modern, lightweight - just fingerprinting and serving. Precompiles in seconds vs minutes.&lt;/td&gt;
&lt;td&gt;No built-in preprocessing (delegates to external tools).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="https://github.com/rails/sprockets" rel="noopener noreferrer"&gt;sprockets&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in Sass/CoffeeScript/ERB compilation, &lt;code&gt;//= require&lt;/code&gt; directives.&lt;/td&gt;
&lt;td&gt;Slow, complex, legacy.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Propshaft does one thing well: fingerprint and serve assets. If you need Sass or CoffeeScript compilation, Sprockets handles it - but you probably don't in 2025.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-asset-pipeline&lt;/code&gt; / &lt;code&gt;-A&lt;/code&gt;&lt;/strong&gt; - No asset pipeline at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hotwire (&lt;code&gt;--skip-hotwire&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://turbo.hotwired.dev/" rel="noopener noreferrer"&gt;Turbo&lt;/a&gt; + &lt;a href="https://stimulus.hotwired.dev/" rel="noopener noreferrer"&gt;Stimulus&lt;/a&gt; - the default Rails frontend framework. Turbo 8 introduced morphing (DOM diffing via &lt;a href="https://github.com/bigskysoftware/idiomorph" rel="noopener noreferrer"&gt;idiomorph&lt;/a&gt;) that makes full-page refreshes feel SPA-smooth. Skip only if you're using a JS SPA framework (React, Vue) or building an API-only app (auto-skipped with &lt;code&gt;--api&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solid Stack &amp;amp; Deployment
&lt;/h2&gt;

&lt;p&gt;These are Rails 8 additions that replace external services with database-backed alternatives.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--skip-solid&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/rails/solid_cache" rel="noopener noreferrer"&gt;Solid Cache&lt;/a&gt; + &lt;a href="https://github.com/rails/solid_queue" rel="noopener noreferrer"&gt;Solid Queue&lt;/a&gt; + &lt;a href="https://github.com/rails/solid_cable" rel="noopener noreferrer"&gt;Solid Cable&lt;/a&gt; - replaces &lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt; for caching, background jobs, and WebSockets. All database-backed, works with SQLite, PostgreSQL, and MySQL. 37signals runs 20M jobs/day on Solid Queue for &lt;a href="https://www.hey.com/" rel="noopener noreferrer"&gt;HEY&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solid Cache&lt;/strong&gt; - database-backed caching. Higher latency than Redis RAM, but terabytes of SSD capacity at a fraction of the cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solid Queue&lt;/strong&gt; - uses &lt;code&gt;FOR UPDATE SKIP LOCKED&lt;/code&gt; for efficient polling. Replaces &lt;a href="https://sidekiq.org/" rel="noopener noreferrer"&gt;Sidekiq&lt;/a&gt;/&lt;a href="https://github.com/resque/resque" rel="noopener noreferrer"&gt;Resque&lt;/a&gt; for most apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solid Cable&lt;/strong&gt; - database-backed Action Cable. Polls every 100ms. Fine for moderate real-time needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip if:&lt;/strong&gt; you already run Redis and need Sidekiq's advanced features (batches, rate limiting) or sub-millisecond cache latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--skip-kamal&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kamal-deploy.org/" rel="noopener noreferrer"&gt;Kamal 2&lt;/a&gt; deploys Docker containers to any VPS (Hetzner, DigitalOcean, AWS EC2). Uses &lt;a href="https://github.com/basecamp/kamal-proxy" rel="noopener noreferrer"&gt;kamal-proxy&lt;/a&gt; (replaces &lt;a href="https://traefik.io/" rel="noopener noreferrer"&gt;Traefik&lt;/a&gt;) with automatic &lt;a href="https://letsencrypt.org/" rel="noopener noreferrer"&gt;Let's Encrypt&lt;/a&gt; SSL. Zero-downtime deploys, rolling restarts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skip if:&lt;/strong&gt; you deploy to a PaaS (Heroku, Render, Fly.io) or use Kubernetes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;--skip-thruster&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/basecamp/thruster" rel="noopener noreferrer"&gt;Thruster&lt;/a&gt; - HTTP/2 proxy (written in Go by 37signals) that sits in front of &lt;a href="https://puma.io/" rel="noopener noreferrer"&gt;Puma&lt;/a&gt;. Provides HTTP/2, gzip compression, asset caching, X-Sendfile, and automatic SSL. Replaces &lt;a href="https://nginx.org/" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt;/&lt;a href="https://caddyserver.com/" rel="noopener noreferrer"&gt;Caddy&lt;/a&gt; for simple deployments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skip if:&lt;/strong&gt; you already have a reverse proxy (Nginx, ALB, Cloudflare) or deploy to a PaaS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks You Can Skip
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Email &amp;amp; Rich Content
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-action-mailer&lt;/code&gt; / &lt;code&gt;-M&lt;/code&gt;&lt;/strong&gt; - No email sending or receiving infrastructure. Skip if your app never sends email.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-action-mailbox&lt;/code&gt;&lt;/strong&gt; - No inbound email routing to controller-like mailboxes. Requires Active Record. Skip if you don't process incoming email.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-action-text&lt;/code&gt;&lt;/strong&gt; - No &lt;a href="https://trix-editor.org/" rel="noopener noreferrer"&gt;Trix&lt;/a&gt; rich text editor integration. Requires Active Record. Auto-skipped in API mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background &amp;amp; Storage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-active-job&lt;/code&gt;&lt;/strong&gt; - No background job framework. Also disables Solid Queue integration. Skip only if you handle no async work at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-active-storage&lt;/code&gt;&lt;/strong&gt; - No file uploads to S3/GCS/Azure. Requires Active Record. Skip if your app handles no file uploads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-action-cable&lt;/code&gt; / &lt;code&gt;-C&lt;/code&gt;&lt;/strong&gt; - No WebSocket framework. Also disables Solid Cable. Skip if you don't need real-time features.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-jbuilder&lt;/code&gt;&lt;/strong&gt; - Removes the &lt;a href="https://github.com/rails/jbuilder" rel="noopener noreferrer"&gt;Jbuilder&lt;/a&gt; JSON template DSL. Most API apps prefer &lt;code&gt;render json:&lt;/code&gt; with serializers instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing &amp;amp; Code Quality
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-test&lt;/code&gt; / &lt;code&gt;-T&lt;/code&gt;&lt;/strong&gt; - Removes &lt;a href="https://github.com/minitest/minitest" rel="noopener noreferrer"&gt;Minitest&lt;/a&gt; setup. Most people skip this to add &lt;a href="https://rspec.info/" rel="noopener noreferrer"&gt;RSpec&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-system-test&lt;/code&gt;&lt;/strong&gt; - Skips &lt;a href="https://github.com/teamcapybara/capybara" rel="noopener noreferrer"&gt;Capybara&lt;/a&gt; browser tests. Auto-skipped in API mode or when tests are skipped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-brakeman&lt;/code&gt;&lt;/strong&gt; - &lt;a href="https://brakemanscanner.org/" rel="noopener noreferrer"&gt;Brakeman&lt;/a&gt; is a static security scanner for Rails that catches SQL injection, XSS, and 33+ other vulnerability types. Runs in seconds. &lt;strong&gt;Keep it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-bundler-audit&lt;/code&gt;&lt;/strong&gt; - New in Rails 8.1. &lt;a href="https://github.com/rubysec/bundler-audit" rel="noopener noreferrer"&gt;bundler-audit&lt;/a&gt; scans your &lt;code&gt;Gemfile.lock&lt;/code&gt; for gems with known CVEs. Complements Brakeman: code scanning + dependency scanning. &lt;strong&gt;Keep it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-rubocop&lt;/code&gt;&lt;/strong&gt; - &lt;a href="https://rubocop.org/" rel="noopener noreferrer"&gt;RuboCop&lt;/a&gt;, Ruby linter, included by default since Rails 8. Keep it or swap in &lt;a href="https://github.com/standardrb/standard" rel="noopener noreferrer"&gt;Standard Ruby&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-ci&lt;/code&gt;&lt;/strong&gt; - Skips the generated &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; workflow. Rails 8.1 CI includes Brakeman and Bundler Audit steps by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure &amp;amp; Housekeeping
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-docker&lt;/code&gt;&lt;/strong&gt; - Skips Dockerfile, .dockerignore, and bin/docker-entrypoint. Skip if you're not containerizing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--devcontainer&lt;/code&gt;&lt;/strong&gt; - Opt-in (not included by default). Generates &lt;a href="https://code.visualstudio.com/docs/devcontainers/containers" rel="noopener noreferrer"&gt;VS Code dev container&lt;/a&gt; config with Redis, database, and Ruby all preconfigured.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-bootsnap&lt;/code&gt;&lt;/strong&gt; - &lt;a href="https://github.com/Shopify/bootsnap" rel="noopener noreferrer"&gt;Bootsnap&lt;/a&gt; caches expensive computations to speed up boot time. Rarely worth skipping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-dev-gems&lt;/code&gt;&lt;/strong&gt; - Skips &lt;a href="https://github.com/rails/web-console" rel="noopener noreferrer"&gt;web-console&lt;/a&gt; and similar development gems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-keeps&lt;/code&gt;&lt;/strong&gt; - Skips .keep files in empty directories. Git doesn't track empty dirs, so .keep files exist to preserve the directory structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-decrypted-diffs&lt;/code&gt;&lt;/strong&gt; - Skips git config for showing decrypted diffs of encrypted credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-git&lt;/code&gt; / &lt;code&gt;-G&lt;/code&gt;&lt;/strong&gt; - Skips &lt;code&gt;git init&lt;/code&gt;, .gitignore, and .gitattributes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--skip-bundle&lt;/code&gt; / &lt;code&gt;-B&lt;/code&gt;&lt;/strong&gt; - Skips &lt;code&gt;bundle install&lt;/code&gt; after generation. Useful in CI or Docker builds where you control dependency installation separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It Together - Common Recipes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Full-stack SaaS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new myapp &lt;span class="nt"&gt;-d&lt;/span&gt; postgresql &lt;span class="nt"&gt;-c&lt;/span&gt; tailwind &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-action-mailbox&lt;/span&gt; &lt;span class="nt"&gt;--skip-action-text&lt;/span&gt; &lt;span class="nt"&gt;--skip-jbuilder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workhorse setup. PostgreSQL, Tailwind, Solid stack, Kamal - all defaults. Skips Minitest (most teams add RSpec), Action Mailbox (few apps process incoming email), Action Text (add it later if you need a rich text editor), and Jbuilder (you'll use &lt;code&gt;render json:&lt;/code&gt; or a serializer).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API backend:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new myapi &lt;span class="nt"&gt;--api&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; postgresql &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-action-mailbox&lt;/span&gt; &lt;span class="nt"&gt;--skip-jbuilder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--api&lt;/code&gt; strips views, assets, cookies, and Hotwire. Skips Minitest for RSpec. Action Mailbox and Jbuilder rarely belong in an API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single-server indie app (the "one person framework"):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new myapp &lt;span class="nt"&gt;-d&lt;/span&gt; sqlite3 &lt;span class="nt"&gt;-c&lt;/span&gt; tailwind &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-action-mailbox&lt;/span&gt; &lt;span class="nt"&gt;--skip-action-text&lt;/span&gt; &lt;span class="nt"&gt;--skip-jbuilder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQLite + Solid stack = no Redis, no PostgreSQL, no external services. Kamal and Thruster handle deployment and SSL. One server, one process, one database file. Add PostgreSQL later if you outgrow it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PaaS deploy (Heroku, Render, Fly.io):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new myapp &lt;span class="nt"&gt;-d&lt;/span&gt; postgresql &lt;span class="nt"&gt;-c&lt;/span&gt; tailwind &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-action-mailbox&lt;/span&gt; &lt;span class="nt"&gt;--skip-action-text&lt;/span&gt; &lt;span class="nt"&gt;--skip-jbuilder&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-kamal&lt;/span&gt; &lt;span class="nt"&gt;--skip-thruster&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same as the SaaS setup but skips Kamal and Thruster - the PaaS handles containers, routing, and SSL for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lean prototype:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new proto &lt;span class="nt"&gt;--minimal&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bare minimum: no mailer, no jobs, no cable, no Hotwire, no Kamal. Add frameworks back as you need them.&lt;/p&gt;




&lt;p&gt;If you don't want to memorize any of this, I built a tool for that. &lt;a href="https://dev.to/svyatov/i-got-tired-of-looking-up-rails-new-flags-so-i-built-a-wizard-for-it-1adl"&gt;create-rails-app&lt;/a&gt; is an interactive CLI wizard that walks you through each option, remembers your choices, and saves reusable presets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;create-rails-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I got tired of looking up `rails new` flags, so I built a wizard for it</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Fri, 27 Feb 2026 19:47:14 +0000</pubDate>
      <link>https://dev.to/svyatov/i-got-tired-of-looking-up-rails-new-flags-so-i-built-a-wizard-for-it-1adl</link>
      <guid>https://dev.to/svyatov/i-got-tired-of-looking-up-rails-new-flags-so-i-built-a-wizard-for-it-1adl</guid>
      <description>&lt;p&gt;Every time I start a new Rails project, the same thing happens. I open the terminal, type &lt;code&gt;rails new&lt;/code&gt;, and then... pause. What was the flag for PostgreSQL? Is it &lt;code&gt;--skip-test&lt;/code&gt; or &lt;code&gt;--skip-tests&lt;/code&gt;? Do I want Propshaft or Sprockets? What about Solid Queue — is that a flag now?&lt;/p&gt;

&lt;p&gt;So I open &lt;code&gt;rails new --help&lt;/code&gt;, scroll through a wall of options, and piece together a command I'll forget by next week.&lt;/p&gt;

&lt;p&gt;After doing this too many times, I built &lt;a href="https://github.com/svyatov/create-rails-app" rel="noopener noreferrer"&gt;create-rails-app&lt;/a&gt; — an interactive CLI wizard that walks you through every &lt;code&gt;rails new&lt;/code&gt; option one at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Instead of memorizing flags, you answer simple questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[01/31] API only application? (no)  ›  Yes / No
[03/31] Database (postgresql)       ›  sqlite3 / postgresql / mysql / trilogy ...
[04/31] JavaScript approach (importmap) › importmap / bun / esbuild / webpack ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each question shows your last-used choice as the default, so repeat projects take seconds.&lt;/p&gt;

&lt;p&gt;At the end, you see the full &lt;code&gt;rails new&lt;/code&gt; command — review it, then run it or go back and tweak your choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things I find useful
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It remembers your choices.&lt;/strong&gt; Next time you run it, your previous selections are pre-filled. Change one or two things and go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presets.&lt;/strong&gt; Save a named configuration and reuse it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;create-rails-app myapp &lt;span class="nt"&gt;--preset&lt;/span&gt; api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have presets for "api", "fullstack", and "minimal" — covers 90% of my projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart skip rules.&lt;/strong&gt; Disable Active Record? It won't ask about databases. Choose API mode? It skips CSS and JavaScript framework questions. The wizard stays short and relevant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Back navigation.&lt;/strong&gt; Changed your mind three questions in? &lt;code&gt;Ctrl+B&lt;/code&gt; goes back. No need to start over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version-aware.&lt;/strong&gt; It detects your installed Rails version (supports 7.2, 8.0, and 8.1) and only shows options that apply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;create-rails-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Run &lt;code&gt;create-rails-app&lt;/code&gt; and follow the prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just use a template?
&lt;/h2&gt;

&lt;p&gt;Rails templates are great for adding code &lt;em&gt;after&lt;/em&gt; project creation. But they don't help with the &lt;code&gt;rails new&lt;/code&gt; flags themselves — the database, JS bundler, asset pipeline, which frameworks to skip. That's the part I kept forgetting, and that's what this tool handles.&lt;/p&gt;




&lt;p&gt;If you start new Rails projects more than once a year and find yourself googling the same flags, give it a try. Feedback and contributions welcome on &lt;a href="https://github.com/svyatov/create-rails-app" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>clsx for Rails views</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Sun, 03 Mar 2024 19:25:38 +0000</pubDate>
      <link>https://dev.to/svyatov/clsx-for-rails-views-i3</link>
      <guid>https://dev.to/svyatov/clsx-for-rails-views-i3</guid>
      <description>&lt;p&gt;Hey, fellow Rubyists!&lt;/p&gt;

&lt;p&gt;Have you ever found yourself wrestling with conditional class strings in your Rails views? Juggling string interpolation, conditional logic, and array manipulation to apply a class or two conditionally? It's like trying to thread a needle in a hurricane. Well, fret no more! Say hello to &lt;a href="https://github.com/svyatov/clsx-rails" rel="noopener noreferrer"&gt;clsx-rails&lt;/a&gt;, the newest member of the Ruby gems family, here to make your life a tad bit easier.&lt;/p&gt;

&lt;p&gt;Inspired by the simplicity of the &lt;a href="https://github.com/lukeed/clsx" rel="noopener noreferrer"&gt;clsx&lt;/a&gt; npm package, &lt;code&gt;clsx-rails&lt;/code&gt; is your Rails view's new best friend. It's a tiny helper with a mighty purpose: to streamline how you handle CSS classes, making your code cleaner, more readable, and, let's be honest, more elegant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;clsx-rails&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Because we've all been there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'baz'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Hello, Rails world!
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It gets the job done, but it's about as graceful as a giraffe on ice skates. With &lt;code&gt;clsx-rails&lt;/code&gt;, you can turn that mess into a one-liner marvel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;baz: &lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Hello, Rails world!
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage Examples
&lt;/h2&gt;

&lt;p&gt;Whether it's a string, a hash, or an array, &lt;code&gt;clsx-rails&lt;/code&gt; handles them all, even nesting them like Russian dolls if that's your jam. It even eliminates any duplicates while at it! And for those who like their code like their coffee—short and strong - there's the &lt;code&gt;cn&lt;/code&gt; alias.&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;# Variadic strings&lt;/span&gt;
&lt;span class="n"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'this'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s1"&gt;'is'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'awesome'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 'this is awesome'&lt;/span&gt;

&lt;span class="c1"&gt;# Hashes with truthy/falsy values&lt;/span&gt;
&lt;span class="n"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;foo: &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;bar: &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;baz: &lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 'foo baz' (assuming the condition is true)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although not advised, it can handle any level of "complexity":&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;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;[[[[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;]]],&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;a: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;b: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sx"&gt;%w[foo bar]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 'a b 1 2 3 4 foo bar'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more details and usage examples in the &lt;a href="https://github.com/svyatov/clsx-rails" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It's Useful
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keeps your views DRY and readable.&lt;/li&gt;
&lt;li&gt;Reduces the mental overhead of handling conditional classes.&lt;/li&gt;
&lt;li&gt;It's like giving your views a neat little toolbelt for CSS class manipulation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, if you're tired of the conditional class string chaos and want to add some syntactic sugar to your Rails views, give &lt;a href="https://github.com/svyatov/clsx-rails" rel="noopener noreferrer"&gt;clsx-rails&lt;/a&gt; a whirl. Your views will thank you, and who knows, you might find yourself with a bit more time for coffee breaks :)&lt;/p&gt;

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

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>css</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to hide Ruby 2.7 deprecation warnings system-wide</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Fri, 24 Apr 2020 23:36:24 +0000</pubDate>
      <link>https://dev.to/svyatov/how-to-hide-ruby-2-7-deprecation-warnings-system-wide-1ajh</link>
      <guid>https://dev.to/svyatov/how-to-hide-ruby-2-7-deprecation-warnings-system-wide-1ajh</guid>
      <description>&lt;p&gt;Are you using &lt;code&gt;rbenv&lt;/code&gt;? Want to hide Ruby 2.7 deprecation warnings system-wide and not to deal with it on a per-project basis? This small tutorial is for you!&lt;/p&gt;

&lt;p&gt;All you have to do is create file &lt;code&gt;~/.rbenv/rbenv.d/exec/hide-deprecations-for-2.7.bash&lt;/code&gt; with the following content:&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;# ~/.rbenv/rbenv.d/exec/hide-deprecations-for-2.7.bash&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RBENV_VERSION&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'2.7'&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RUBYOPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-W:no-deprecated -W:no-experimental"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;RUBYOPT
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;How exactly does it work can be found &lt;a href="https://github.com/rbenv/rbenv/wiki/Authoring-plugins#rbenv-hooks" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've tested it in Zsh. It should work in Bash, but I can't guarantee it.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>rbenv</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Keep your Javascript dependencies under control</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Mon, 04 Mar 2019 15:48:27 +0000</pubDate>
      <link>https://dev.to/svyatov/keep-your-javascript-dependencies-under-control-4fkn</link>
      <guid>https://dev.to/svyatov/keep-your-javascript-dependencies-under-control-4fkn</guid>
      <description>&lt;p&gt;With all the Javascript libraries and their dependencies these days it’s easy to get carried away and lost track of how heavy your frontend is.&lt;/p&gt;

&lt;p&gt;Here is a great tool for Webpack backed applications: &lt;a href="https://github.com/webpack-contrib/webpack-bundle-analyzer" rel="noopener noreferrer"&gt;Webpack Bundle Analyzer&lt;/a&gt;. It shows the exact size (parsed and gzipped included) of each dependency you put inside your &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;And here is an example of how to add it to your Rails project.&lt;/p&gt;

&lt;p&gt;First, we need to add it to the &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Save the package to your `devDependencies`&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; webpack-bundle-analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, add this to your &lt;code&gt;config/webpack/environment.js&lt;/code&gt; file, right before &lt;code&gt;module.exports = environment;&lt;/code&gt; line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ANALYZE_BUNDLE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BundleAnalyzerPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack-bundle-analyzer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;BundleAnalyzerPlugin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BundleAnalyzer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BundleAnalyzerPlugin&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third, make it available as &lt;code&gt;yarn/npm run&lt;/code&gt; task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// package.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;analyze&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ANALYZE_BUNDLE=true RAILS_ENV=production ./bin/webpack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. You can run it like this now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn run analyze
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy keeping your Javascript dependencies under control! :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>webdev</category>
      <category>rails</category>
    </item>
    <item>
      <title>Easier usage of Rails 5.2 credentials and app-specific configuration</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Sun, 24 Feb 2019 14:21:39 +0000</pubDate>
      <link>https://dev.to/svyatov/easier-usage-of-rails-52-credentials-and-app-specific-configuration-461g</link>
      <guid>https://dev.to/svyatov/easier-usage-of-rails-52-credentials-and-app-specific-configuration-461g</guid>
      <description>&lt;p&gt;As you all know by now, Rails 5.2 introduced a new feature called &lt;a href="https://github.com/rails/rails/pull/30067" rel="noopener noreferrer"&gt;&lt;code&gt;Credentials&lt;/code&gt;&lt;/a&gt;. DHH said the following in the PR:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This new file is a flat format, not divided by environments like secrets.yml has been. Most of the time, these credentials are only relevant in production, and if someone does need to have some keys duplicated for different environments, it can be done by hand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And as you should know by now, Rails 6.0 &lt;a href="https://github.com/rails/rails/pull/33521" rel="noopener noreferrer"&gt;fixes&lt;/a&gt; this obvious inconvenience.&lt;/p&gt;

&lt;p&gt;Meantime, a commonly proposed solution for Rails 5.2 was just to add environments by hands, something like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;facebook_app_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;facebook_app_secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;facebook_app_namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;stripe_publishable_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;stripe_secret_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;stripe_signing_secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;facebook_app_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;facebook_app_secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;facebook_app_namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;stripe_publishable_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;stripe_secret_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
  &lt;span class="na"&gt;stripe_signing_secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then use it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="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;credentials&lt;/span&gt;&lt;span class="p"&gt;[&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;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:facebook_app_secret&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty long and not very readable, right? Yeah, you probably don’t use credentials in that many places in your app anyway, but still. This line has 47 characters about Rails and just 22 characters about what you need. Not the best ratio, in my opinion.&lt;/p&gt;

&lt;p&gt;The solution I’d like to show you is quite obvious, but I’ve never seen it being suggested anywhere (maybe I didn’t search right enough, sorry if that’s the case). &lt;/p&gt;

&lt;p&gt;Just open &lt;code&gt;config/application.rb&lt;/code&gt; and add &lt;code&gt;credentials&lt;/code&gt; method like so:&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_relative&lt;/span&gt; &lt;span class="s1"&gt;'boot'&lt;/span&gt;

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

&lt;span class="c1"&gt;# Require the gems listed in Gemfile, including any gems&lt;/span&gt;
&lt;span class="c1"&gt;# you've limited to :test, :development, or :production.&lt;/span&gt;
&lt;span class="no"&gt;Bundler&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="o"&gt;*&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;groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;YourApp&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;Application&lt;/span&gt;
    &lt;span class="c1"&gt;# Initialize configuration defaults for originally generated Rails version.&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_defaults&lt;/span&gt; &lt;span class="mf"&gt;5.2&lt;/span&gt;

    &lt;span class="c1"&gt;# Settings in config/environments/* take precedence over those specified here.&lt;/span&gt;
    &lt;span class="c1"&gt;# Application configuration can go into files in config/initializers&lt;/span&gt;
    &lt;span class="c1"&gt;# -- all .rb files in that directory are automatically loaded after loading&lt;/span&gt;
    &lt;span class="c1"&gt;# the framework and any gems in your application.&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credentials&lt;/span&gt;
    &lt;span class="vi"&gt;@credentials&lt;/span&gt; &lt;span class="o"&gt;||=&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;credentials&lt;/span&gt;&lt;span class="p"&gt;[&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;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s see what it changes:&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;# Before:&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;credentials&lt;/span&gt;&lt;span class="p"&gt;[&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;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:facebook_app_secret&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# After&lt;/span&gt;
&lt;span class="no"&gt;YourApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:facebook_app_secret&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach abstracts Rails-specific details away, makes it concise, expressive and about your application. As a bonus it gives you a lot of flexibility: you can replace Rails credentials with something else, you can merge credentials from different places, you can easily upgrade to Rails 6 credentials by removing &lt;code&gt;[Rails.env.to_sym]&lt;/code&gt; part, and so on.&lt;/p&gt;

&lt;p&gt;OK, that’s great, but post’s title was also saying something about “app-specific configuration,” right? Correct! I want to show you one more thing that can make your life with Rails a little easier.&lt;/p&gt;

&lt;p&gt;As your Rails application grows sooner or later, you will need a place to store various environment-specific details for your app: things that aren’t secrets or credentials, just some custom configuration. Rails documentation even has a section with this exact name: &lt;a href="https://guides.rubyonrails.org/v5.2/configuring.html#custom-configuration" rel="noopener noreferrer"&gt;Custom configuration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;According to the documentation Rails offers us two pretty powerful options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;config.x&lt;/code&gt; namespace&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config_for&lt;/code&gt; method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neat! How about we use our credentials approach described above and combine with these two options?&lt;/p&gt;

&lt;p&gt;Step 1: create &lt;code&gt;config/app.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;shared&lt;/span&gt;
  &lt;span class="na"&gt;facebook_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://www.facebook.com/mysite'&lt;/span&gt;
  &lt;span class="na"&gt;twitter_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://twitter.com/mysite'&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*shared&lt;/span&gt;
  &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:3000'&lt;/span&gt;
  &lt;span class="na"&gt;devise_mailer_sender&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no-reply@localhost'&lt;/span&gt;
  &lt;span class="na"&gt;orders_mailer_sender&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no-reply@localhost'&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*shared&lt;/span&gt;
  &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mysite.com'&lt;/span&gt;
  &lt;span class="na"&gt;devise_mailer_sender&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;no-reply@mysite.com'&lt;/span&gt;
  &lt;span class="na"&gt;orders_mailer_sender&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;orders@mysite.com'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: fill in &lt;code&gt;config.x&lt;/code&gt; from &lt;code&gt;app.yml&lt;/code&gt; in the &lt;code&gt;config/application.rb&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# App specific configuration&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config_for&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="nf"&gt;with_indifferent_access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: add &lt;code&gt;config&lt;/code&gt; method to the &lt;code&gt;config/application.rb&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="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;config&lt;/span&gt;
    &lt;span class="vi"&gt;@config&lt;/span&gt; &lt;span class="o"&gt;||=&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;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So your &lt;code&gt;config/application.rb&lt;/code&gt; file now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'boot'&lt;/span&gt;

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

&lt;span class="c1"&gt;# Require the gems listed in Gemfile, including any gems&lt;/span&gt;
&lt;span class="c1"&gt;# you've limited to :test, :development, or :production.&lt;/span&gt;
&lt;span class="no"&gt;Bundler&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="o"&gt;*&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;groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;YourApp&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;Application&lt;/span&gt;
    &lt;span class="c1"&gt;# Initialize configuration defaults for originally generated Rails version.&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_defaults&lt;/span&gt; &lt;span class="mf"&gt;5.2&lt;/span&gt;

    &lt;span class="c1"&gt;# Settings in config/environments/* take precedence over those specified here.&lt;/span&gt;
    &lt;span class="c1"&gt;# Application configuration can go into files in config/initializers&lt;/span&gt;
    &lt;span class="c1"&gt;# -- all .rb files in that directory are automatically loaded after loading&lt;/span&gt;
    &lt;span class="c1"&gt;# the framework and any gems in your application.&lt;/span&gt;

    &lt;span class="c1"&gt;# App-specific configuration&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config_for&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="nf"&gt;with_indifferent_access&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;
    &lt;span class="vi"&gt;@config&lt;/span&gt; &lt;span class="o"&gt;||=&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;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credentials&lt;/span&gt;
    &lt;span class="vi"&gt;@credentials&lt;/span&gt; &lt;span class="o"&gt;||=&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;credentials&lt;/span&gt;&lt;span class="p"&gt;[&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;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can use our custom configuration like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;YourApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:devise_mailer_sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How cool is that? :)&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to send Rails deprecation warnings to Airbrake</title>
      <dc:creator>Leonid Svyatov</dc:creator>
      <pubDate>Mon, 18 Feb 2019 21:04:20 +0000</pubDate>
      <link>https://dev.to/svyatov/how-to-send-rails-deprecation-warnings-to-airbrake-51bh</link>
      <guid>https://dev.to/svyatov/how-to-send-rails-deprecation-warnings-to-airbrake-51bh</guid>
      <description>&lt;p&gt;We’re upgrading our Ruby on Rails version from 4.2 to 5.2 this week. A long-awaited change for us. Of course, there are a lot of deprecation warnings that was thrown at us during this process. Rubocop and tests caught the vast majority of those, but we don’t have 100% code coverage, so some of these warnings got into production.&lt;/p&gt;

&lt;p&gt;In development Rails send these warnings to the log file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Print deprecation notices to the Rails logger.&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_support&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deprecation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A reasonable default, but I changed it to &lt;code&gt;:raise&lt;/code&gt;. It's way faster to find and deal with the warnings this way in development.&lt;/p&gt;

&lt;p&gt;For production environment Rails uses &lt;a href="https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html" rel="noopener noreferrer"&gt;&lt;code&gt;ActiveSupport::Notifications&lt;/code&gt;&lt;/a&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;# Send deprecation notices to registered listeners.&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_support&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deprecation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:notify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that nobody listens for it in production. Fortunately, that was easy to fix with Airbrake. I tried to “google” the solution at first but didn’t find anything useful, so I’m sharing my solution for other seeking souls like me :)&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/initializers/deprecations_notifier.rb&lt;/span&gt;

&lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'deprecation.rails'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_finish&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;DeprecationException&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;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:message&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_backtrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:callstack&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:to_s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;gem_name: &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:gem_name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;deprecation_horizon: &lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:deprecation_horizon&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="no"&gt;Airbrake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;notice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:context&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:severity&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'warning'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re using &lt;a href="https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html" rel="noopener noreferrer"&gt;&lt;code&gt;CurrentAttributes&lt;/code&gt;&lt;/a&gt; and storing &lt;code&gt;request.uuid&lt;/code&gt; there it would be a good idea to add current request UUID to the &lt;code&gt;params&lt;/code&gt; as well.&lt;/p&gt;

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