Skip to content

Rails Style Guide

AnthonySuper edited this page Dec 7, 2014 · 2 revisions

General

Follow our Ruby Style Guide at all times.

Avoid N+1 queries if at all possible. Use methods like include and joins to prevent this from happening.

Models

Segregate your code into sections. This is best explained with an example:

class TagGroup < ActiveRecord::Base
  #################
  # RELATIONSHIPS #
  #################
  belongs_to :image
  has_many :tags, through: :tag_group_members
  has_many :tag_group_members
  
  ###############
  # VALIDATIONS #
  ###############
  validates :image, presence: true
  validates :tags, presence: true
  
  ##############
  # ATTRIBUTES #
  ##############
  attr_accessor :tag_group_string

  #############
  # CALLBACKS #
  #############
  before_validation :save_tag_group_string
  after_initialize :load_tag_group_string
 
  #################
  # CLASS METHODS #
  #################

  ##
  # This method takes an array of tag names, or a properly
  # formatted string,  and returns all placements
  # which have tags by those names.
  def self.by_tag_names(names)

    if names.is_a? Array
      to_search = names
    else
      names.split(",").map{|x| x.downcase.strip.squish}
    end
	  self.joins(:tags).where(tags:{name: to_search})
  end
  ####################
  # INSTANCE METHODS #
  ####################

  private
  def save_tag_group_string
    return unless self.tag_group_string && ! self.tag_group_string.empty?
    array = self.tag_group_string.split(",")
      .map{|str| str.strip.squish.downcase} # Properly format the names
      .map{|str| Tag.where(name: str).first_or_create} # Create or find
    self.tags = array
  end
  def load_tag_group_string
    return unless self.tags.any?
    self.tag_group_string = self.tags.map(&:name).join(", ")
  end
end

Never use has_and_belongs_to_many, instead using has_many :through.

Routing

Prefer RESTful routes.

Use nested routes for models with a very tight relationship. Never nest more than once.

resources :images do
  resources :tag_groups
end

Shallow nesting is also good, although it's not currently in our codebase. This is also true of Concerns. If you can find a use case for them, you should probably use it.

Use member routing where possible.

The string ":controller" should not appear in a routing string. Ever. Same goes for ":action". Both are a security risk.

Testing

We use RSpec to write our tests.

Test as much code as you reasonably can. You do not necessarily have to test first, write code later. Sometimes it's best to start getting an outline before you write tests, but it's always good to test as soon as possible.

All models must have a valid factory. You don't need to write the factory validation yourself, since we have one global test that does that. Factories which are intentionally invalid should have names that start with "invalid".

Prefer shoulda matchers to manual testing.

Clone this wiki locally