do |ruby| right — Useful Callbacks and ActiveRecord Options

How many of you have ever felt personally victimized by your own decision to skim-read documentation?
How many of you have ever felt personally victimized by your own decision to skim-read documentation?

Ruby on Rails is well-documented, but that means there’s a lot to go through. Of course you read all documentation for your languages, but just in case, here are some Ruby on Rails callbacks and relationship options that will cleanup, simplify, and clarify your code.

Callbacks

Technically, a “callback” is just executable code that is passed as an argument to a function. Ruby describes their callbacks as hooks into object life cycles, where a “hook” is a way to execute code before, after, or instead of existing code. Personally, I like the word choice of React — “lifecycle method.” These Ruby callbacks/hooks/lifecycle methods simplify code by telling X to always run before or after Y.

The most common callbacks are before_ and after_create, _initialize, _save, _update, and _destroy. See a complete list here. The callback before_destroy points out an important distinction between delete and destroy. If an object is removed via .delete, these callbacks are not called, but if it is removed via .destroy, these callbacks are called. Make sense? Destroy runs callbacks, delete does not. Think of “complete destruction,” because it completes the callbacks, but “complete deletion” doesn’t sound as cool, so it does not call those methods. Let’s take a closer look.

Regina George: This is a Ruby on Rails callback. I have your app’s hooks. Could you have her call me back? It’s urgent.
Regina George: This is a Ruby on Rails callback. I have your app’s hooks. Could you have her call me back? It’s urgent.
You can count on Ruby’s callbacks to work!

The next three examples do the same thing — they make sure the user’s email is lowercase before it’s saved.

A common syntax is “before_create :method_here”

The above syntax is very common. Just type “before_create” and then a space, a colon, and the name of the method. Make sure to define the method in the class (line 5).

Another way is to write the function with “do” after “before_create”

In some cases, it might be more convenient to just write the function along with before_create using “do.”

Lastly, we can use { |pipes| inside curly braces} instead of “do”

All three methods work! Lastly, you can also add if statements to Ruby callbacks.

before_save :do_this_method, if: :this_method_returns_true

Pretty handy! Thanks, apidock.com!

Callbacks — check! belongs_to options and mean girl memes left to do
Callbacks — check! belongs_to options and mean girl memes left to do

Options for belongs_to

Similar to callbacks, ActiveRecord belongs_to options perform tasks at appropriate times in the object’s lifecycle.

dependent

The option dependent: can work very similarly to before_destroy above.

belongs_to :user, dependent: :destroy

Here, we are telling the “choice” class that its objects must be removed when their user is removed — dependent: :destroy. Choices are destroyed with their users (but users are not destroyed with their choices, at least that we can see from this code). Referencing the discussion on destroy vs delete above, this will call the destroy callbacks for choices, as well.

counter_cache

The option :counter_cache keeps a running count of the number of objects in the relationship. If I wanted easy access to the number of choices my user has made, I would write

belongs_to :user, counter_cache: true

To work, this requires a column in “user” called “choices_count”. Otherwise, you can replace true with the column name. I had already made the column by the wrong name, so I thought it was easier to adjust to that.

belongs_to: :user, counter_cache: :choice_count

Note that this only increments the count and does not decrement upon deletion.

class_name & foreign_key

Lastly, you can rename relationships using :class_name and :foreign_key. This option works with belongs_to and has_many.

I needed to distinguish between foods that users have chosen (line 5) and foods that users have made (line 7). To make this distinction obvious to ActiveRecord, I refer to the latter as made_foods. Only foods that have the user’s ID in the user_id column are the user’s made_foods.

Karen Smith: If you’re from “foods,” why are you “made foods?”
Karen Smith: If you’re from “foods,” why are you “made foods?”

Final Thoughts

Ruby on Rails is amazing, and it’s even better when you know how to use it’s toolset well. So…

Karen Smith: There’s a 30% chance that you’re already reading my blog
Karen Smith: There’s a 30% chance that you’re already reading my blog

What are your favorite Ruby tools? Let us know in the comments!

Full Stack Web Developer, former English as a foreign language teacher and volleyball coach. All views and opinions are my own.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store