Last Updated: January 30, 2020
·
4.693K
· dejnon

Conditional chaining of methods

Problem

I have seen the following pattern repeatedly:

institution_users =
  if params[:is_internal]
    User.
      for_institution(some_id).
      only_name_and_email.
      internal_only
  else
    User.
      for_institution(some_id).
      only_name_and_email.
      external_only
  end

It is quite unreadable as you end up reading the same code twice, wondering as there is any difference between method chains...

Solution

Instead consider the following:

users_for_institution = lambda {
  User.
    for_institution(some_id).
    only_name_and_email
}

institution_users =
  if params[:is_internal]
    users_for_institution.call.internal_only
  else
    users_for_institution.call.external_only
  end

Of course you can also nest more methods chains:

users_for_institution = lambda { |some_id|
  User.
    for_institution(some_id).
    only_name_and_email
}

internal_users = lambda {
  users_for_institution.
    call(123).
    internal_only
}

internal_users.call.sorted # only one DB query

Conclusion

The presented technique is fairly basic.
Sometimes it make the code more efficient (avoids hitting DB multiple times).
The biggest benefit I see here is that it removes the unnecessary code duplication (DRY).