How do I change what a paid plan unlocks in my app?
To gate a feature, add include RequireEntitlement to its controller. To ungate it, delete that line. To change what counts as paid at all, edit the single strategy line in app/models/entitlement.rb. Those are two different decisions and they live in two different places on purpose.
Two questions, two places
Which surfaces are paid? One line per controller. Adding the include gates it; removing it frees it.
What does paid mean? One line in app/models/entitlement.rb, which returns the strategy: a
subscription, a token balance, or nothing.
Keeping them apart is what makes each change cheap. A pricing experiment that moves a feature in or out of the paid tier touches one controller and no billing code. A business model change touches one model and no controllers.
Tiers, if you need more than one
Subscription has a tier enum with free and pro. entitled? ignores it, because the shipped
gate is binary: you are in or you are not.
For a real tier split, the honest version is a second question rather than a cleverer version of the first:
Entitlement.for(Current.account).entitled?
Current.account.subscription&.pro?
Resist encoding tiers into RequireEntitlement. The moment the concern knows about plan names, every
controller that includes it is coupled to your pricing page, and pricing changes more often than
code.
Do not confuse this with authorization
Entitlement asks whether the workspace may use the surface. Pundit asks whether this user may touch
this record. A gated controller still needs authorize and policy_scope, and the policies live in
app/policies. Skipping the second one means paying customers can read each other's data, which is
the worst version of this mistake.
Check both paths
bin/rspec
Every gated controller wants two request specs: entitled gets 200, unentitled is redirected. The
example Project slice has both, and copying its spec file is faster than writing them.
Changing a gate on a live app
Adding a gate to a feature people already use locks out existing users at the moment of deploy. Usually worth announcing first, or grandfathering by giving existing accounts an active subscription row before the deploy rather than after the complaints.