0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

Using scopes in Rails 4

09 August, 2014

I was introduced to scopes in Rails through my need to chain queries to get the result I needed. This site's hero navigation filters post titles from different categories. I need to display projects on the right and all other categories on the left.

The only category common to both is hero
Scopes in Rails are basically a way to define methods on a model, in such a way that you can retrieve data and information on a subset of a database.

Example:
This snippet defines two scopes on the Post model: hero and projects
Note that the scope uses associations I have set up between Post and Category

1
2
3
#scope that isolates "heroes" and "projects"
scope :hero, -> {Post.includes(:categories).where('categories.title = (?)', "Hero")}
scope :projects, -> {Post.includes(:categories).where('categories.title = (?)', "Projects")}

This will help me do the following:

1
2
Post.hero #basically returns all posts filed under "Hero" catgegory
Post.projects #Returns all posts under "Projects"

This also helps me do some advanced stuff such as chaining queries. I have a method that helps me filter drafts. Then, I merge the two queries to get only non-draft posts that fall under Projects and Hero

1
2
3
4
5
6
7
8
#checks for the is_draft flag
def self.is_draft(what)
   post = Post.where('is_draft = (?)', what )
end

#controller
#this is how you merge the two scopes and then get the desired result
@projects = Post.is_draft("no").projects & Post.hero

Scopes are a great way of working with subsets of your database that you work with frequently. To put it in context, I am often going to need to work with Project posts and I want the convenience of calling a method on the model, which feels natural.