More Generic Scopes

This is a followup to my previous post How to share code among ActiveRecord models. In this installment I’m going to show some additional generic scopes that I found useful for building up queries. In particular, some of these scopes are twice as generic, because they are defined by wrappers, so that their real name is specific enough to be meaningful.

Field Scope

This scope sets a field to some value. Think about a state field. Instead of writing

{[ .state-where | 1.hljs(=ruby=) ]}

you can write

{[ .state-with | 1.hljs(=ruby=) ]}

which is a bit easier to read.

Here it is.

{[ .field_scope | 1.hljs(=ruby=) ]}

Example:

{[ .field_scope-example | 1.hljs(=ruby=) ]}

What I like about this generic scope is that a common word like state becomes a specific term that I can later easily find with a simple and fast text search. So, instead of searching for state, whose matches could include a lot of false positives, I can search for with_state which is specific enough to only match what I’m really looking for. Anyway this is a dull surrogate of what future IDEs (able to understand semantics) will allow, like search for specific usages of common words.

Belonging-To Scope

This scope works analogously to the previous one, but for belongs_to relations. Think about a user_id field. Instead of writing

{[ .belongingto-before | 1.hljs(=ruby=) ]}

you can write

{[ .belongingto-after | 1.hljs(=ruby=) ]}

which is a bit easier to read.

It’s almost always possible to guess the name of the field from the class of the object a model is supposed to belong to. If that’s not the case, I’ve provided an as option that accepts the name of the field (without the _id suffix).

{[ .belongingto-scope | 1.hljs(=ruby=) ]}

Example:

{[ .belongingto-example | 1.hljs(=ruby=) ]}

Polymorphic Scope

This scope works analogously to the previous one, but for belongs_to relations that are also polymorphic. In this case, I decided to retain simplicity by means of the with_ prefix. Think about a liked field that has been defined like this

{[ .liked-poly | 1.hljs(=ruby=) ]}

Then it’s a bit tedious (and rude) to explicitly refer to liked_table and liked_id in queries, so this is how to elegantly magic them away.

{[ .poly_scope | 1.hljs(=ruby=) ]}

All the sti_* methods account for Single Table Inheritance, which is a little tricky to deal with because of how it works behind the scenes.

Example:

{[ .poly_scope-example | 1.hljs(=ruby=) ]}

Note how natural it all becomes, working equally well for classes (also for STI classes, like Artist < User) and objects (like Lady Gaga).