Skip to content

Instantly share code, notes, and snippets.

@vaxinate
Last active August 9, 2016 21:57
Show Gist options
  • Save vaxinate/b3b9d4245bafe2d0d3631fb0572694f3 to your computer and use it in GitHub Desktop.
Save vaxinate/b3b9d4245bafe2d0d3631fb0572694f3 to your computer and use it in GitHub Desktop.
class Author < ActiveRecord::Base
has_many :books
# this is bad
def scifi_books
books.by_category('scifi')
end
# this is better (with caveats?). The caveat is that as the number of associated records increases
# this will get slower, and may get to a point where it's best to fall back to a more complex SQL
# query that JOINs the associated records using a sub-query that handles the filtering, but I feel
# like in general, it's a premature optimization until you're actually experiencing noticable
# lags in responsiveness
def fantasy_books
books.select { |book| book.category == 'fantasy' }
end
end
class Book < ActiveRecord::Base
belongs_to :author
scope :by_cagegory, -> (cat_name) { where(category: cat_name) }
scope :published_after, -> (after_date) { where('published_at > ?', after_date) }
scope :includes_author, -> { includes(:author) }
# this is a good way to use scopes! This could technically also be defined as a scope
# itself, but it would go well past the limit of 80 chars per line so I defined it as a
# class method instead. You can use scopes and class methods interchangably in this way
# in practice, but it's best to use scopes for short fragments, and class methods to
# build compositions of scopes.
def self.new_in_category(category)
Book.by_category(category).published_after(Time.zone.now - 1.year).includes_author
end
end
json.authors @authors do |author|
json.name author.name
json.scifi_books @author.scifi_books do |book|
# the scifi_books method will ALWAYS do a query since it's using a scope internally
json.title book.title
end
json.fantasy_books @author.fantasy_books do |book|
# the fantasy_books method will not query as long as you've already brought in the associated
# records with your initial query in the controller with either #includes or #joins
json.title book.title
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment