Skip to content

Latest commit

 

History

History
495 lines (459 loc) · 8.06 KB

ruby-standards.md

File metadata and controls

495 lines (459 loc) · 8.06 KB

Ruby Guidelines

here are our best practices when it comes to ruby and on rails.

Indentation

We only use spaces for indentation rather than hard tabs.

Classes

We prefer two-space indents.

# bad
class Car
    def initialize(params)
    end
end
# good
class Car
  def initialize(params)
  end
end

Method Parameters

We prefer to neatly stack long method arguments.

# bad
class Car
  def self.create(brand_id, brand_name, manufacturer_year, chassis_type,
                  rubber_type, number_of_doors, transmition_type, country_of_origin)
    ...
  end
end
# good
class Car
  def self.create(brand_id,
                  brand_name,
                  manufacturer_year,
                  chassis_type,
                  rubber_type,
                  number_of_doors,
                  transmition_type,
                  country_of_origin)
    ...
  end
end
# good
class Car
  def self.create(
    brand_id,
    brand_name,
    manufacturer_year,
    chassis_type,
    rubber_type,
    number_of_doors,
    transmition_type,
    country_of_origin
  )
    ...
  end
end

Method Body: Multi-line boolean statements

We prefer to properly indent Multi-line boolean statements with indentation.

# bad
def can_race?(car)
  Fia::CarStandards.check_qualification?(car) &&
  is_fuel_check_passed? &&
  is_with_wheels?
end
# good
def can_race?(car)
  Fia::CarStandards.check_qualification?(car) &&
    is_fuel_check_passed? &&
    is_with_wheels?
end

Control Statements: Case Statements

# bad
case color
  when 'red'
    puts 'ferrari'
  when 'blue'
    puts 'ford'
  when 'black'
    puts 'nissan'
  else
    puts 'just a car'
end
# good
case color
when 'red'
  puts 'ferrari'
when 'blue'
  puts 'ford'
when 'black'
  puts 'nissan'
else
  'just a car'
end

Control Statements: If Statements

# bad
result = if cool?
  do_something_cool
else
  do_something_uncool
end
# good
result =
  if cool?
    do_something_cool
  else
    do_something_uncool
  end

Control Statements: If modifier statements

We use if modifiers if the condition can fit within one line else, we avoid using it

# bad
some_very_long_statement_about_coding_and_managing_states(some_very_long_variable_naming_convention) if valid?
# good
if valid?
  some_very_long_statement_about_coding_and_managing_states(some_very_long_variable_naming_convention)
end

Chaining method calls

# bad
Car.create(params).add_detail.select_time_compound.race
# good
Car
  .create(params)
  .add_detail
  .select_time_compound
  .race

Lines Terminations

Methods

We use single empty line to terminate method definitions.

# bad
def create_drink(raw_ingredients)
  prepared_ingredients = init_ingredients(raw_ingredients)
  drink = mix(prepared_ingredients)
  garnish_drink(drink)
end
def init_ingredients(ingredients)
  ...
end
def mix_ingredients(ingredients)
  ...
end
def garnish_drink(drink)
  ...
end
# good
def create_drink(raw_ingredients)
  prepared_ingredients = init_ingredients(raw_ingredients)
  drink = mix(prepared_ingredients)
  garnish_drink(drink)
end

def init_ingredients(ingredients)
  ...
end

def mix_ingredients(ingredients)
  ...
end

def garnish_drink(drink)
  ...
end

Attribute Accessors

We use single empty line to terminate declartion of accessors.

# bad
class Car
  attr_reader :brand
  def initialize
    ...
  end
end
# good
class Car
  attr_reader :brand

  def initialize
    ...
  end
end

Method Privacy policies

We use single empty line to terminate declartion of privacy policies.

# bad
class Car
  def initialize
    ...
  end
  private
  def tire_compound
    ...
  end
end
# good
class Car
  def initialize
    ...
  end

  private

  def tire_compound
    ...
  end
end

Trailing Commas

We avoid commas after the last parameter in a method call.

# bad
def create(brand_id, brand_name, manufacturer_year,)
  ...
end
# bad
def create(brand_id, brand_name, manufacturer_year)
  ...
end

String line continuations

We use "backslashes" as a point of continuation for long strings.

# good
long_string = 'The quick brown fox jumps over the lazy dog' \
              ' cat, elephant, tiger, goose, goat, mouse' \
              ' human, and alien.'

Naming Conventions

Method Suffixes

For methods that are expecting boolean as a return value, we use "?" as a suffix

# bad
def race_worthy(car)
  ...
end
# good
def race_worthy?(car)
  ...
end

For methods that are implying that it will modify something, we use "!" as a suffix

# bad
class Car
  def retire(car)
    car.destroy!
  end
end
# good
class Car
  def retire!(car)
    car.destroy!
  end
end

Method Prefixes

We avoid using prefixes such as "is, does or can" but we properly allot a meaningful adjective.

# bad
def can_race?(car)
  ...
end

def is_aerodynamic?(car)
  ...
end
# good
def race_worthy?(car)
  ...
end

def aerodynamic?(car)
  ...
end

We use "_" for unused variables

# bad
def get_driver_license(driver)
  personal_data, license = register_driver(driver)
  return license
end
# good
get_driver_license(driver)
  _personal_data, license = register_driver(driver)
  return license
end

Control Statements

Built-in Ruby iterators over for loops

We definitely don't use for loop, not unless we had no choice, but instead use Ruby's array of iterators

# bad
numbers = [1, 2, 3]
for number in numbers do
  puts number + 1
end
# good
numbers = [1, 2, 3]
numbers.each {|number| number + 1}

Ternary Operators over if else statements

We use ternary operators in place of single if else statments

# bad
result = if condition then do_something else do_something_else end
# good
result = condition ? do_something : do_something_else end

Nested Ternary Operators

Terneries are not meant to be nested. We fix this by introducing a layer of single if else statement

# bad
condition then (nested_condition ? nested_do_something : do_something) else do_something_else end
# good
if condition
  nested_condition ? nested_do_something : do_something
else
  do_something_else
end

Nested Conditionals

We avoid nested conditionals as this could be prove to be difficult to read. In these cases, we prefer to use guard clauses.

# bad
def prepare_car(car)
  if car
    install_tires(car)
    if car.soft_compound_tires?
      set_stop_strategy(2)
    else
      set_stop_strategy(1)
    end
  end
end
# bad
def prepare_car(car)
  return if car.blank?
  install_tires(car)
  return set_stop_strategy(2) if car.soft_compound_tires?
  set_stop_strategy(1)
end

Safe Navigation and delegation

We avoid using chained "&" but we replace it with check instead.

# bad
driver&.address&.zip_code
# good
driver && driver.address&.zip_code

Or we can use delegation

# good
class Driver
  def zip_code
    address&.zip_code
  end
end

Method Definitions

Keyword Arguments

We seldom use positional arguments, but in place we use keyword arguments.

# bad
def officiate_race(drivers, teams = [], cars = [], country = '', race_date = Time.now)
  ...
end
# good
def officiate_race(drivers, teams: [], cars: [], country: '', race_date: Time.now)
  ...
end

Or if keyword arguments are not yet available, just use options hash instead

# good
def officiate_race(drivers, options)
  options = {
    teams: [],
    cars: [],
    country: '',
    race_date: Time.now
  }.merge(options)
  ...
end

Variable Assignment

Constants

There are no such thing as constants ni Ruby as these so called constants are mutable. In order to workaround this issue, we call freeeze on our so called constants.

# bad
class Car
  WHEELS = 4
  COLORS = [
    'red',
    'blue',
    'yellow'
  ]
end
# good
class Car
  WHEELS = 4.freeze
  COLORS = [
    'red',
    'blue',
    'yellow'
  ].freeze
end