---
title: Decimating deprecated finders
teaser: 'Use synvert snippets to automatically rewrite ruby code for a smoother upgrade
  path to Rails 5.

  '
tags: parsing,ruby,rails upgrade,rails 5,rails
author: Jesse Bailey
published_on: 2019-12-11
---

I imagine that while planning the release of Rails 5, and considering the
prospect of maintaining the [activerecord-deprecated_finders] gem,
the rails team had the following to say:

> Nope!*

The impact being that every sad soul who put off replacing old style finder
syntax, like

```ruby
Post.find(:all, conditions: { published_on: 2.weeks.ago }, limit: 5 ...)
```

or any dynamic finders,

```ruby
find_all_by_...
find_last_by_...
scoped_by_...
find_or_initialize_by_...
find_or_create_by_...
```

with the new syntax,

```ruby
Post.where(published_on: 2.weeks.ago).limit(5)
Post.find_all_by(author: 'Shakespeare', ...)
```

was/is in a bit of a pickle.

Maybe this was easy for you, maybe you proactively began this process
long before the Rails 5 release (you know... to be ready).

But maybe, just maybe,
Rails upgrades slid down into the dark basement beneath your house of
Important Things To Do&trade; and remained there,
glaring silently at you from the abyss, waiting.
I've recently had the pleasure of descending into such dungeons, and I'm here to
tell you there is hope!

I'm speaking to you, yes you.

I've found something that might help you slay this brooding beast.
A Sword of Glamification (Level 29)...

[Synvert]

Befriend your "boo" in the basement and give it the glow-up it's always deserved.
Make it clean, updated, secure, and a friend of developers everywhere.

Just sprinkle a few [synvert snippets][rails-snippets] onto its weary
code-bones.

```bash
# Handles find with hash options
$ synvert -r rails/convert_models_2_3_to_3_0

# Handles dynamic finders
$ synvert -r rails/convert_dynamic_finders
```

and, by the magic of AST tree parsing,
deprecated finders melt into beautiful chains of method invocations.

Obviously this won't solve all your upgrade woes,
but it's a good place to start.
The changes made should be well reviewed.
There are still some edge cases where the modifications
don't produce the desired change.
And, as always, it is highly valuable (one might also say indispensable)
to have a solid test suite with good coverage to ensure app logic still meets
expectations.

There are other [snippets][synvert-snippets] for rewriting ruby/rails code, so
check those out. Maybe one of them solves something you've been dreading for a
long time.

## Parser

If you are interested in learning about parsing and rewriting ruby code,
check out [Parser], the gem that [Synvert] (and also [Rubocop]) depend on
to accomplish their ruby-rewriting functionality. It provides a way to create
your own [rewriters].

## How'd you find this... glad you asked

At this point, the important information has been shared.
However, if you want to hear about a solid yak-shave... Read on.

Shockingly, I didn't find this tool via usual search-foo like
`"remove rails deprecated finders"`. Actually, I accidentally found the
rails snippets while searching for a library for parsing ruby.

But to get to that point...

1. Automation!
2. Starts writing tediously crafted regex in `sed` calls
3. Spends considerable time on this...
  > Wait, the hash condition arguments could appear in any order
  > and the method call could span multiple lines...

5. Dies a bit inside
6. Quits development and
  [moves to Tibet to study the secrets of an attachment free life][Tibet]
7. During final months of training must traverse a mountain pass to yak lair
   and retrieve a golden hair
8. Shaves a yak
9. Returns with yak hair to teacher
  > *Me*: Have I succeeded in my training master?<br>
  > *Master*: You lack only one final thing<br>
  > *Me*: What is that?<br>
  > *Master*: You must finish what you began<br>
  > *Me*: It is impossible, no Regex can handle the task<br>
  > *Master*: Look into the code, and see it looks out at you, parse the
  secrets of the Ruby<br>
  > *Me*: Of course! A parser!

10. Searches internet for ruby parsing lib, finding [Parser], which links
    to an [article about its DSL for rewriting ruby code][rewriters]
    > Wonder if someone has created libraries that use this functionality?

12. Searches for other gems that depend on it, which leads to [Synvert][Synvert-Website]
13. Starts attempting to write a [Synvert::Rewriter] to change deprecated finders
    (and actually gets pretty far pretty quickly)
14. Sees link on website to synvert snippets and realizes that directory
    contains [snippets for rewriting ruby code for rails upgrades][rails-snippets]

🤦 So yeah, that's how it went down.

## Footnotes

*: _Not an actual quote from the rails team_

[Synvert]: https://github.com/xinminlabs/synvert
[Synvert-Website]: http://xinminlabs.github.io/synvert/
[Synvert::Rewriter]: http://xinminlabs.github.io/synvert/dsl/
[Parser]: https://github.com/whitequark/parser
[ast]: https://github.com/whitequark/ast
[rewriters]: https://whitequark.org/blog/2013/04/26/lets-play-with-ruby-code/
[Rubocop]: https://github.com/rubocop-hq/rubocop
[activerecord-deprecated_finders]: https://github.com/rails/activerecord-deprecated_finders
[rails-snippets]: https://github.com/xinminlabs/synvert-snippets/tree/master/lib/rails
[synvert-snippets]: https://github.com/xinminlabs/synvert-snippets/tree/master/lib
[Tibet]: https://en.wikipedia.org/wiki/Seven_Years_in_Tibet
