Easy Redesign in Rails: Run Old and New Side by Side with :variants.
Redesigning a mature Rails app can feel like a minefield. You're still pushing hotfixes to production, QA needs to validate existing behavior, and stakeholders want to compare the old and new versions side by side. Imagine being able to render both designs on the same page — safely, in the same app, with minimal code overhead and in production.
That’s where :variants
come in.
What are Rails view :variants?
Most Rails developers know :variants
as a way to serve different templates depending on device or context — like mobile vs. desktop. But the magic is that variants are format‑agnostic, so they can be used for any variation of a view.
Under the hood, when you use:
render variants: [:mobile, :desktop]
Rails will look for templates in this order:
• app/views/home/index.html+mobile.erb
• app/views/home/index.html+desktop.erb
• app/views/home/index.html.erb (fallback)
Perfect for device differences, sure — but it unlocks a more powerful use: design rollouts. You can add a +redesign
version of your template, and Rails will choose it when request.variant = :redesign
is set in your controller.
Because variants are supported throughout Rails, this approach works seamlessly with layouts
, partials
, mailers
, and even ViewComponent
templates. And since the logic for switching lives in a single place (setting request.variant
), you avoid littering your views with scattered if statements or duplicating controller logic.
Cookie-Free: Run Both Designs Side by Side
You might be tempted to toggle the redesign with a cookie, but for this use case I prefer using a simple URL parameter instead. By passing ?redesign=true
on every internal link, you can keep the old and new design running in separate browser windows or tabs at the same time. That's incredibly useful during a redesign process, because QA testers, designers, or developers can compare both versions side by side without clearing cookies or switching accounts.
Rails makes this easy with default_url_options
. You can override it in your controller (or ApplicationController) to automatically add the :redesign
parameter whenever it's present in the request:
def default_url_options
params[:redesign].present? ? {redesign: true} : {}
end
How to Wire Variants into Your Rails App
Instead of duplicating the variant-switching code in every controller, a cleaner approach is to extract it into a concern. This way you can include it wherever you need the redesign toggle, and keep the logic consistent across your app.
For example, create a concern in app/controllers/concerns/redesign.rb
:
module Redesign
extend ActiveSupport::Concern
included do
before_action :set_redesign_variant
end
private
def default_url_options
params[:redesign].present? ? {redesign: true} : {}
end
def set_redesign_variant
if params[:redesign].present?
request.variant = :redesign
end
end
end
You can then add this concern to any controller where you want redesign support: include Redesign
.
With this setup, any request including ?redesign=true
will automatically render the +redesign
templates for that controller's views. The best part is that the logic lives in one place, making it easy to maintain and adjust later (e.g., feature flags, user-specific rollouts).
Full Support Across Rails Rendering Features
The great thing about variants is that they don’t just work with regular views. The same mechanism applies to layouts, partials, mailers, and even ViewComponent templates. That means you can keep both old and new versions cleanly separated without sprinkling conditional logic all over your code. Wherever Rails looks for a template, it also looks for the variant — giving you full coverage for a redesign, end to end.
Wrapping Up
The code examples in this post are meant as orientation — you'll likely need to adapt and refine them to fit your app. The key takeaway is that Rails variants are a powerful tool for handling redesigns. They let you keep old and new designs running in parallel, making it easier to test, compare, and roll out gradually.
In a real project, you’ll also want to think about who can access the redesign. Maybe you add a simple switcher in the UI, but only show it to specific users, or restrict it by office IPs. Feature flags and role checks are natural ways to manage that.
Finally, variants can even help you track your progress. By checking which views already have a +redesign template and which don’t, you can measure how much work is left before the old design can be retired.
Using :variants
this way keeps your redesign process safe, transparent, and incremental — no more big-bang releases.