More readable integer comparisons in Ruby
Let’s be honest: comparison operators like <, >, <= and >= work perfectly fine, but they’re not so readable (even more so when you’re scanning through code quickly or working with complex conditionals).
What if instead of writing seats < 10 you could write seats.below? 10? Or usage.at_least? limit instead of usage >= limit? Much clearer, right?
This is where refinements come in handy (in short: add methods to existing classes without the risks of monkey patching).
Here’s a simple refinement module that I copy between my apps to make integer comparisons more expressive:
# lib/comparable_integer.rb (reusable modules and classes are stored in `lib/`)
module ComparableInteger
refine Integer do
def below?(other)
self < other
end
def above?(other)
self > other
end
def at_most?(other)
self <= other
end
def at_least?(other)
self >= other
end
end
end
Now imagine you’re building subscription logic that checks seat limits:
class SubscriptionsController < ApplicationController
using ComparableInteger
def upgrade
if current_seats.below? requested_seats
charge_additional_seats
update_subscription
redirect_to subscription_path, notice: "Upgraded successfully"
else
redirect_to subscription_path, alert: "Cannot downgrade seats"
end
end
private
def current_seats = @subscription.seats
def requested_seats = params[:seats].to_i
end
The code reads almost like plain English. current_seats.below? requested_seats is immediately clear, while current_seats < requested_seats requires a mental translation.
Or another example when dealing with pricing tiers or feature limits:
class FeatureAccess
using ComparableInteger
def initialize(subscription)
@subscription = subscription
end
def can_access_advanced_analytics?
@subscription.amount_in_cents.at_least? 4999
end
def needs_team_plan?
@subscription.seats.above? 1
end
def qualifies_for_discount?
@subscription.months_active.at_least? 12
end
end
Much more readable than a sea of >= and > symbols, don’t you think? Got more ideas for making Ruby code more expressive? Let me know in the comments below.
Want to read me more?
-
Alternative to Ruby's Monkey Patching
Ruby's refinements are a cleaner solution to the sharp knife that is monkey patching. This aricle explore how to use them along with some real life examples. -
User-Specific Content in Turbo Stream Partials
Learn how to conditionally show user-specific content in Rails Turbo Stream partials using a custom turbo-show element for client-side rendering. -
Simple Stripe Billing for Rails
Getting paying users has never been simpler with Stripe and Rails. Let's go over the tiny amount of code needed today.
Over to you…
What did you like about this article? Learned something knew? Found something is missing or even broken? 🫣 Let me (and others) know!
Comments are powered by Chirp Form
{{comment}}