Skip to content

Latest commit

 

History

History

rails-tips

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

ProctorU Guides

Guides is a foundation of best practices used by ProctorU's Engineering & Design team. It includes best practices for Code Reviewing, Style Rules, and much more.


Rails Tips

Rails tips are fun tid-bits of info that aren't best practices or opinionated.

Models

  • Use with_options to group associations.

    class Account < ApplicationRecord
      # ok
      has_many :customers, dependent: :destroy
      has_many :products, dependent: :destroy
      has_many :invoices, dependent: :destroy
      has_many :expenses, dependent: :destroy
    
      # preferred
      with_options dependent: :destroy do
        has_many :customers
        has_many :products
        has_many :invoices
        has_many :expenses
      end
    end
  • On ActiveRecord relations, use any? or exists? instead of present?.

    Each method determines if at least one record exists, but present? needs to load each record queried, while any? uses a SQL count statement and exists? only needs to load 1 record. Removing the unnecessary database hits brought by present? provides a significant improvement in speed when dealing with ActiveRecord relations.

    For example, where a Client has_many Projects:

    # bad, loads all Project records (slow)
    Client.find(20).projects.where(status: 'finished').present?
    
    # better, uses a count statement on associated Projects (faster)
    Client.find(20).projects.where(status: 'finished').any?
    
    # best, only tries to load one Project and stops if it finds one (fastest)
    Client.find(20).projects.where(status: 'finished').exists?

    Read more on this topic here.

Views

  • Avoid rendering partials in loops. Instead, render a collection, so Rails only needs to evaluate the necessary partial one time.

    Also, cache partials so they don't need to be re-evaluated every page load.

    For example, when rendering a collection (in HAML)

    # bad, rails must evaluate the 'user' partial for every record in the collection
    - users.each do |user|
      = render partial: 'shared/user'
    
    # good, rails only needs to evaluate the 'user' partial one time
    = render users, cached: true
    
    # or, if the collection isn't an ActiveRecord Collection (an array, maybe):
    = render partial: 'shared/user', collection: users, as: :user, cached: true

    Read more on this topic here.

Benchmarking

  • Benchmarking is the best way to determine performance differences between different methods in ruby.

    require 'benchmark'
    
    Benchmark.bmbm do |x|
      x.report('Thing 1') do
        # Do some ruby...
      end
    
      x.report('Thing 2') do
        # Do some other ruby...
      end
    end

Decorators

Decorators should be used to abstract object presentation away from models, controllers, or views (or any other intermediary layer). Objects can be "decorated", which adds behavior to the instance.

Do use decorators for

  • Things like @user.first_name (object presentation)
  • Things where object manipulation is repeated like name.gsub("-", " ").titleize in views or date formatting.

Don't use decorators for

  • Model logic
  • Complex view logic (Facades are better patterns for that)
  • Anything that tries to modify the actual object (ie. saving/updating)