Ognjen Regoje bio photo

Ognjen Regoje
But you can call me Oggy


I make things that run on the web (mostly).
More ABOUT me and my PROJECTS.

me@ognjen.io LinkedIn

Put Rails scopes nearer to where they're used

#rails #technical

Rails scopes are normally put all together near the top of the file, similar to this:

scope :latest, -> { where(retried: [false, nil]) }
scope :retried, -> { where(retried: true) }
scope :ordered, -> { order(:name) }
scope :ordered_by_stage, -> { order(stage_idx: :asc) }
scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }

This has the benefit of being able to view all of them in one place.

This is fine for generic scopes that might be used in many different places. However, for scopes that are predominantly for one feature that is often very far from where they’re used. This greatly reduces readability. You have to jump up and down.

Instead, what I’ve started doing is keeping them closer to where they’re actually used.

scope :latest, -> { where(retried: [false, nil]) }

def update_older_statuses_retried!
  self.class
    .latest
    .where(name: name)
    .where.not(id: id)
    .update_all(retried: true, processed: true)
end

This greatly improves readability.

The downside is that it might sometimes be difficult to find where it’s defined. However, given that I’d Ctrl+F for the definition anyways, that hasn’t been a problem so far.

For further development, what I’d like to do is extend the annotate_models gem to add scopes as well to the top of the file.