Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Rails Designer
Rails Designer

Posted on • Originally published atrailsdesigner.com

     

Alternative to Ruby's Monkey Patching

This article was originally published onRails Designer's Build a SaaS with Ruby on Rails


One of the joys of working with Ruby is it allows you to write code almost however you want, one feature that allows you to this is “monkey patching”: modifying methods in any class at runtime. This is truly a sharp knife: you might know where and how you use it, but third-parties, like gems, are not aware of your patches.

In this article, I want to highlight a better way to it instead:refinements.

Refinements was introduced in Ruby 2.0. It allows you to refine a class or module locally. Let's see an example (from the Ruby docs):

classCdeffooputs"C#foo"endendmoduleMrefineCdodeffooputs"C#foo in M"endendend
Enter fullscreen modeExit fullscreen mode

Alright, you define a module (M) and therefine the class you want (C).

c=C.newc.foo# => prints "C#foo"usingMc=C.newc.foo# => prints "C#foo in M"
Enter fullscreen modeExit fullscreen mode

Let's look at some real life examples from my own apps. I put these refinements in thelib folder as that's where I add all classes/modules that can be copied from app to app without modifications.

# lib/hash_dot.rbmoduleHashDotrefineHashdodefto_dotJSON.parseto_json,object_class:OpenStructendendend
Enter fullscreen modeExit fullscreen mode

Then wherever you want to use it, addto_dot to the hash:

classSubscriptionsController<ApplicationControllerusingHashDotdefcreateSubscription.create\name:data.plan_type,\# instead of data.dig(:plan_type)status:data.status# instead of data.dig(:status)endprivatedefdata{plan_type:"professional",status:"active",billing_cycle:"monthly",amount_in_cents:2999,features:["unlimited_storage","team_collaboration","api_access"],seats:5,next_billing_at:1740369856,trial_ends_at:nil,created_at:1732421070}.to_dotendend
Enter fullscreen modeExit fullscreen mode

Another example:

# lib/to_timestamp.rbmoduleToTimestamprefineIntegerdodefto_timestampTime.at(self)endendrefineNilClassdodefto_timestampnilendendend
Enter fullscreen modeExit fullscreen mode

The data in theSubscriptionsController uses UNIX timestamps (like Stripe does), let's use the refinement too, by callingto_timestamp onnext_billing_at:

classSubscriptionsController<ApplicationControllerusingHashDotusingToTimestampdefcreateSubscription.create\name:data.plan_type,\status:data.status,\next_billing_at:data.next_billing_at.to_timestampendprivatedefdata{plan_type:"professional",status:"active",billing_cycle:"monthly",amount_in_cents:2999,features:["unlimited_storage","team_collaboration","api_access"],seats:5,next_billing_at:1740369856,trial_ends_at:nil,created_at:1732421070}.to_dotendend
Enter fullscreen modeExit fullscreen mode

When callingto_timestamp it will convert it usingTime.at:

data.next_billing_at.to_timestamp# => 2025-02-24 12:00:00 +0000
Enter fullscreen modeExit fullscreen mode

And that are some examples of using refinements. Got more suggestions or use cases? Let me know below. 👇

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I help teams around the world make their Rails apps a bit nicer to maintain and look at. 🎨 Also kickstart SaaS' in a month. 👷 And built a Rails UI Components library, used by 1000+ developers. 🚀
  • Location
    Amsterdam, The Netherlands
  • Joined

More fromRails Designer

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp