The Refactor Challenge

Hello! Share one small refactor in Ruby that made your code cleaner. It could be:

  • Simplifying a method
  • Extracting logic
  • Improving readability
  • Using a built-in Ruby method instead of custom logic

Please share before and after snippets and try to keep it simple.

1 Like

The one I tweak the most is simply:
arr.each{|item| item.do_something() }
to
arr.each(&:do_something)

A little thing, but the less punctuation and the fewer visible blocks the easier it is to read.

I also do Extract Method a lot.

5 Likes

Before

I had this inside a controller that used a private method to return the expected response:

render json: jsend(status: response.status, data: build_promotion_data(enabled_promotion))
def build_promotion_data(promotion)
  return {} unless promotion

  {
    title: promotion.short_title,
    amount: promotion.amount,
    expiration_date: promotion.expiration_date
  }
end

After

Extracted logic into a presenter to separate responsibilities and to move expiration date and title logic into a new object so it could be reused in different places:

data = EnabledPromotionPresenter.new(promotion:, purchase:).show
render json: jsend(status: response.status, data:)
class EnabledPromotionPresenter
  attr_reader :promotion, :purchase

  def initialize(promotion:, purchase:)
    @promotion = promotion
    @purchase = purchase
  end

  def show
    return {} unless promotion

    cashback_promotion = Promotions::Cashback.new(promotion:, purchase:)

    {
      title: cashback_promotion.title,
      amount: cashback_promotion.amount,
      expiration_date: cashback_promotion.expiration_date
    }
  end
end
1 Like

I like the &:do_something shortcut too!

Starting from ruby 3.4, that code could be written with it as default block parameter: arr.each { it.do_something } but I haven’t used it yet. Do you like that new syntax?

I don’t think I’d change a reference to it if I came across one. But I’m also not in the habit of writing it that way.

1 Like

A refactor I often do is converting local variables into methods as much as I can.

Before

def something_here_to_do
  expected_result = result

  if expected_result
    foo
  else
    bar
  end
end

After

def something_here_to_do
  if result?
    foo
  else
    bar
  end
end

def result?
  # some processing
end
2 Likes