Skip to content

Instantly share code, notes, and snippets.

@scmx
Last active February 17, 2023 11:28
Show Gist options
  • Save scmx/132d887ecf7e4c72fb02bb3860027ede to your computer and use it in GitHub Desktop.
Save scmx/132d887ecf7e4c72fb02bb3860027ede to your computer and use it in GitHub Desktop.
7 Patterns to Refactor Rails Models 7 years later #rails #model #refactor #valueobject #serviceobject #formobject #queryobject #viewobject #policyobject #decorator

7 Patterns to Refactor Rails Models 7 years later

You may have read the following excellent blogpost by Brian Helmkamp of CodeClimate. It nicely describes 7 types of objects that can be extracted from models and controllers in a Rails-app.

7 Patterns to Refactor Fat ActiveRecord Models https://codeclimate.com/blog/7-ways-to-decompose-fat-activerecord-models/ Brian Helmkamp on Oct 17, 2012.

Here are my thoughts on it, reading it as an experienced rails developer, 7 years later 😅 👴

Be careful about extracting code into app/model/concerns.

Any application with an app/concerns directory is concerning. :thinking_face: I've heard that quote before, probably repeated on an episode of Ruby Rogues.

We need to practise this more @standout projects.

These are often put in app/services and are pretty common. The name is not the best.

These days you can use include ActiveModel::Model` to make it easier. Check out the "Form Objects in Rails" blogpost by Chris Jeon https://typefast.blog/form-objects-rails/)

When scope isn't enough.

Helpers are terribly global. You can't really have private methods since including a module in ruby will expose all its methods even if they're private. And by default all helpers are available everywhere 🙀.

How about view objects then, do they solve the problem? Yes I think so. But where should they be put? Everything needs to have it's place 📚. Maybe app/view_models.

The gem pundit by Varvet is very popular for this, at least within my bubble @standout.

As Dan Croak of thoughtbot concluded in Evaluating Alternative Decorator Implementations In Ruby.

  1. Start by wrapping an object with a plain old ruby object
  2. If you need a transparent interface you can reach for SimpleDelegator and friends
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment