105
PRESENTED BY KRISHNA SRIHARI Masymbol Technologies Ruby Style Guide

Ruby on Rails

Embed Size (px)

DESCRIPTION

Ruby on Rails to build versatile web applications that are developed and launched quickly, which significantly lower overall costs

Citation preview

Page 1: Ruby on Rails

PRESENTED BY KRISHNA SRIHARIMasymbol Technologies

Ruby Style Guide

Page 2: Ruby on Rails

Source Code Layout

Page 3: Ruby on Rails

Use two spaces per indentation level

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - four spacesdef some_method do_somethingend

# gooddef some_method do_somethingend

Page 4: Ruby on Rails

Don't use ; to separate statements and expressions. As a corollary - use one expression per line.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badputs 'foobar'; # superfluous semicolon

puts 'foo'; puts 'bar' # two expressions on the same line

# goodputs 'foobar'

puts 'foo'puts 'bar'

puts 'foo', 'bar' # this applies to puts in particular

Page 5: Ruby on Rails

Prefer a single-line format for class definitions with no body

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badclass FooError < StandardErrorend

# okishclass FooError < StandardError; end

# goodFooError = Class.new(StandardError)

Page 6: Ruby on Rails

Avoid single-line methods.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddef too_much; something; something_else; end

# okish - notice that the first ; is requireddef no_braces_method; body end

# okish - notice that the second ; is optionaldef no_braces_method; body; end

# okish - valid syntax, but no ; makes it kind of hard to readdef some_method() body end

# gooddef some_method bodyend

Page 7: Ruby on Rails

Use spaces around operators, after commas, colons and semicolons, around { and before }.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

sum = 1 + 2a, b = 1, 2[1, 2, 3].each { |e| puts e }class FooError < StandardError; end

# bade = M * c ** 2

# goode = M * c**2

Page 8: Ruby on Rails

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# good - space after { and before }{ one: 1, two: 2 }

# good - no space after { and before }{one: 1, two: 2}

# good - no spaces"string#{expr}"

# ok - arguably more readable"string#{ expr }"

No spaces after (, [ or before ], ). [link]

some(arg).other[1, 2, 3].size

Page 9: Ruby on Rails

Indent when as deep as case

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badcase when song.name == 'Misty' puts 'Not again!' when song.duration > 120 puts 'Too long!' when Time.now.hour > 21 puts "It's too late" else song.playend

# goodcasewhen song.name == 'Misty' puts 'Not again!'when song.duration > 120 puts 'Too long!'when Time.now.hour > 21 puts "It's too late"else song.playend

Page 10: Ruby on Rails

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - pretty convolutedkind = case yearwhen 1850..1889 then 'Blues'when 1890..1909 then 'Ragtime'when 1910..1929 then 'New Orleans Jazz'when 1930..1939 then 'Swing'when 1940..1950 then 'Bebop'else 'Jazz'end

result = if some_cond calc_somethingelse calc_something_elseend

Page 11: Ruby on Rails

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# good - it's apparent what's going onkind = case year when 1850..1889 then 'Blues' when 1890..1909 then 'Ragtime' when 1910..1929 then 'New Orleans Jazz' when 1930..1939 then 'Swing' when 1940..1950 then 'Bebop' else 'Jazz' end

result = if some_cond calc_something else calc_something_else end

Page 12: Ruby on Rails

Use empty lines between method definitions and also to break up a method into logical paragraphs internally

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

def some_method data = initialize(options)

data.manipulate!

data.resultend

def some_method resultend

Page 13: Ruby on Rails

Use spaces around the = operator when assigning default values to method parameters

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddef some_method(arg1=:default, arg2=nil, arg3=[]) # do something...end

# gooddef some_method(arg1 = :default, arg2 = nil, arg3 = []) # do something...end

Page 14: Ruby on Rails

Avoid line continuation \ where not required. In practice, avoid using line continuations for anything but string concatenation.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badresult = 1 - \ 2

# good (but still ugly as hell)result = 1 \ - 2

long_string = 'First part of the long string' \ ' and second part of the long string'

Page 15: Ruby on Rails

(Option A) When continuing a chained method invocation on another line keep the . on the second line

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - need to consult first line to understand second lineone.two.three. four

# good - it's immediately clear what's going on the second lineone.two.three .four

Page 16: Ruby on Rails

Align the parameters of a method call if they span more than one line.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# starting point (line is too long)def send_mail(source) Mailer.deliver(to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text)end

# bad (double indent)def send_mail(source) Mailer.deliver( to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text)end

Page 17: Ruby on Rails

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# gooddef send_mail(source) Mailer.deliver(to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text)end

# good (normal indent)def send_mail(source) Mailer.deliver( to: '[email protected]', from: '[email protected]', subject: 'Important message', body: source.text )end

Page 18: Ruby on Rails

Align the elements of array literals spanning multiple lines.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - single indentmenu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']

# goodmenu_item = [ 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']

# goodmenu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']

Page 19: Ruby on Rails

Add underscores to large numeric literals to improve their readability

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - how many 0s are there?num = 1000000

# good - much easier to parse for the human brainnum = 1_000_000

Page 20: Ruby on Rails

Limits and space

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Use RDoc and its conventions for API documentation. Don't put an empty line between the comment block and the def.

Limit lines to 80 characters.

Avoid trailing whitespace.

End each file with a newline.

Don't use block comments. They cannot be preceded by whitespace and are not as easy to spot as regular comments. [link]

Page 21: Ruby on Rails

Don't use block comments

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad=begincomment lineanother comment line=end

# good# comment line# another comment line

Page 22: Ruby on Rails

Syntax

Page 23: Ruby on Rails

Use :: only to reference constants(this includes classes and modules) and constructors

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badSomeClass::some_methodsome_object::some_method

# goodSomeClass.some_methodsome_object.some_methodSomeModule::SomeClass::SOME_CONSTSomeModule::SomeClass()

Page 24: Ruby on Rails

Use def with parentheses when there are arguments. Omit the parentheses when the method doesn't accept any arguments.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddef some_method() # body omittedend

# gooddef some_method # body omittedend

# baddef some_method_with_arguments arg1, arg2 # body omittedend

# gooddef some_method_with_arguments(arg1, arg2) # body omittedend

Page 25: Ruby on Rails

Never use for, unless you know exactly why. Most of the time iterators should be used instead. for is implemented in terms of each

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

arr = [1, 2, 3]

# badfor elem in arr do puts elemend

# note that elem is accessible outside of the for loopelem # => 3

# goodarr.each { |elem| puts elem }

# elem is not accessible outside each's blockelem # => NameError: undefined local variable or method `elem'

Page 26: Ruby on Rails

Never use then for multi-line if/unless

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badif some_condition then # body omittedend

# goodif some_condition # body omittedend

Page 27: Ruby on Rails

Favor the ternary operator(?:) over if/then/else/end constructs

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badresult = if some_condition then something else something_else end

# goodresult = some_condition ? something : something_else

Page 28: Ruby on Rails

Use one expression per branch in a ternary operator. This also means that ternary operators must not be nested. Prefer if/else constructs in these cases.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badsome_condition ? (nested_condition ? nested_something : nested_something_else) : something_else

# goodif some_condition nested_condition ? nested_something : nested_something_elseelse something_elseend

Page 29: Ruby on Rails

Leverage the fact that if and case are expressions which return a result

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badif condition result = xelse result = yend

# goodresult = if condition x else y end

Page 30: Ruby on Rails

Avoid the use of !!

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badx = 'test'# obscure nil checkif !!x # body omittedend

x = false# double negation is useless on booleans!!x # => false

# goodx = 'test'unless x.nil? # body omittedend

Page 31: Ruby on Rails

The and and or keywords are banned. It's just not worth it. Always use && and || instead.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad# boolean expressionif some_condition and some_other_condition do_somethingend

# control flowdocument.saved? or document.save!

# good# boolean expressionif some_condition && some_other_condition do_somethingend

# control flowdocument.saved? || document.save!

Page 32: Ruby on Rails

Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badif some_condition do_somethingend

# gooddo_something if some_condition

# another good optionsome_condition && do_something

Page 33: Ruby on Rails

Avoid modifier if/unless usage at the end of a non-trivial multi-line block.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad10.times do # multi-line body omittedend if some_condition

# goodif some_condition 10.times do # multi-line body omitted endend

Page 34: Ruby on Rails

Favor unless over if for negative conditions (or control flow ||)

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddo_something if !some_condition

# baddo_something if not some_condition

# gooddo_something unless some_condition

# another good optionsome_condition || do_something

Page 35: Ruby on Rails

Never use unless with else. Rewrite these with the positive case first.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badunless success? puts 'failure'else puts 'success'end

# goodif success? puts 'success'else puts 'failure'end

Page 36: Ruby on Rails

Don't use parentheses around the condition of an if/unless/while/until

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badif (x > 10) # body omittedend

# goodif x > 10 # body omittedend

Page 37: Ruby on Rails

Never use while/until condition do for multi-line while/until

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badwhile x > 5 do # body omittedend

until x > 5 do # body omittedend

# goodwhile x > 5 # body omittedend

until x > 5 # body omittedend

Page 38: Ruby on Rails

Favor modifier while/until usage when you have a single-line body.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badwhile some_condition do_somethingend

# gooddo_something while some_condition

Page 39: Ruby on Rails

Favor until over while for negative conditions

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddo_something while !some_condition

# gooddo_something until some_condition

Page 40: Ruby on Rails

Use Kernel#loop instead of while/until when you need an infinite loop

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badwhile true do_somethingend

until false do_somethingend

# goodloop do do_somethingend

Page 41: Ruby on Rails

Use Kernel#loop with break rather than begin/end/until or begin/end/while for post-loop tests.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badbegin puts val val += 1end while val < 0

# goodloop do puts val val += 1 break unless val < 0end

Page 42: Ruby on Rails

Omit parentheses around parameters for methods that are part of an internal DSL

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Omit parentheses around parameters for methods that are part of an internal DSL (e.g. Rake, Rails, RSpec), methods that have "keyword" status in Ruby (e.g. attr_reader, puts) and attribute access methods.

Use parentheses around the arguments of all other method invocations.

Page 43: Ruby on Rails

Omit the outer braces around an implicit options hash

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baduser.set({ name: 'John', age: 45, permissions: { read: true } })

# gooduser.set(name: 'John', age: 45, permissions: { read: true })

Page 44: Ruby on Rails

Omit both the outer braces and parentheses for methods that are part of an internal DSL

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Person < ActiveRecord::Base # bad validates(:name, { presence: true, length: { within: 1..10 } })

# good validates :name, presence: true, length: { within: 1..10 }end

Page 45: Ruby on Rails

Omit parentheses for method calls with no arguments

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badKernel.exit!()2.even?()fork()'test'.upcase()

# goodKernel.exit!2.even?fork'test'.upcase

Page 46: Ruby on Rails

Use two spaces per indentation level

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Page 47: Ruby on Rails

Prefer {...} over do...end for single-line blocks. Avoid using {...} for multi-line blocks

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

names = ['Bozhidar', 'Steve', 'Sarah']# badnames.each do |name| puts nameend# goodnames.each { |name| puts name }# badnames.select do |name| name.start_with?('S')end.map { |name| name.upcase }# goodnames.select { |name| name.start_with?('S') }.map { |name| name.upcase }

Page 48: Ruby on Rails

Consider using explicit block argument to avoid writing block literal that just passes its arguments to another block

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

require 'tempfile'

# baddef with_tmp_dir Dir.mktmpdir do |tmp_dir| # block just passes arguments Dir.chdir(tmp_dir) { |dir| yield dir } endend

# gooddef with_tmp_dir(&block) Dir.mktmpdir do |tmp_dir| Dir.chdir(tmp_dir, &block) endend

with_tmp_dir do |dir| puts "dir is accessible set: #{dir}"end

Page 49: Ruby on Rails

Avoid return where not required for flow of control

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddef some_method(some_arr) return some_arr.sizeend

# gooddef some_method(some_arr) some_arr.sizeend

Page 50: Ruby on Rails

As a corollary, avoid shadowing methods with local variables unless they are both equivalent.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Foo attr_accessor :options # ok def initialize(options) self.options = options # both options and self.options # are equivalent here end # bad def do_something(options = {}) unless options[:when] == :later output(self.options[:message]) end end

# good def do_something(params = {}) unless params[:when] == :later output(options[:message]) end endend

Page 51: Ruby on Rails

Use shorthand self assignment operators whenever applicable.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badx = x + yx = x * yx = x**yx = x / yx = x || yx = x && y

# goodx += yx *= yx **= yx /= yx ||= yx &&= y

Page 52: Ruby on Rails

Use ||= to initialize variables only if they're not already initialized

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badname = name ? name : 'Bozhidar'

# badname = 'Bozhidar' unless name

# good - set name to Bozhidar, only if it's nil or falsename ||= 'Bozhidar'

Page 53: Ruby on Rails

Don't use ||= to initialize boolean variables.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - would set enabled to true even if it was falseenabled ||= true

# goodenabled = true if enabled.nil?

Page 54: Ruby on Rails

Use &&= to preprocess variables that may or may not exist. Using &&= will change the value only if it exists, removing the need to check its existence with if

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badif something something = something.downcaseend

# badsomething = something ? something.downcase : nil

# oksomething = something.downcase if something

# goodsomething = something && something.downcase

# bettersomething &&= something.downcase

Page 55: Ruby on Rails

Avoid explicit use of the case equality operator ===

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badArray === something(1..100) === 7/something/ === some_string

# goodsomething.is_a?(Array)(1..100).include?(7)some_string =~ /something/

Page 56: Ruby on Rails

Avoid using Perl-style special variables (like $:, $;, etc.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad$:.unshift File.dirname(__FILE__)

# goodrequire 'English'$LOAD_PATH.unshift File.dirname(__FILE__)

Page 57: Ruby on Rails

Never put a space between a method name and the opening parenthesis

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badf (3 + 2) + 1

# goodf(3 + 2) + 1

Page 58: Ruby on Rails

Use the new lambda literal syntax for single line body blocks. Use the lambda method for multi-line blocks

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badl = lambda { |a, b| a + b }l.call(1, 2)

# correct, but looks extremely awkwardl = ->(a, b) do tmp = a * 7 tmp * b / 50end

# goodl = ->(a, b) { a + b }l.call(1, 2)

l = lambda do |a, b| tmp = a * 7 tmp * b / 50end

Page 59: Ruby on Rails

Prefer proc over Proc.new

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badp = Proc.new { |n| puts n }

# goodp = proc { |n| puts n }

Page 60: Ruby on Rails

Prefix with _ unused block parameters and local variables. It's also acceptable to use just _

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badresult = hash.map { |k, v| v + 1 }

def something(x) unused_var, used_var = some(x) # ...end

# goodresult = hash.map { |_k, v| v + 1 }

def something(x) _unused_var, used_var = something_else(x) # ...end

# goodresult = hash.map { |_, v| v + 1 }

def something(x) _, used_var = something_else(x) # ...end

Page 61: Ruby on Rails

Prefer proc.call() over proc[] or proc.() for both lambdas and procs.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - looks similar to Enumeration accessl = ->(v) { puts v }l[1]

# also bad - uncommon syntaxl = ->(v) { puts v }l.(1)

# goodl = ->(v) { puts v }l.call(1)

Page 62: Ruby on Rails

Prefix with _ unused block parameters and local variables. It's also acceptable to use just _

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badresult = hash.map { |k, v| v + 1 }

def something(x) unused_var, used_var = some(x) # ...end

# goodresult = hash.map { |_k, v| v + 1 }

def something(x) _unused_var, used_var = something_else(x) # ...end

# goodresult = hash.map { |_, v| v + 1 }

def something(x) _, used_var = something_else(x) # ...end

Page 63: Ruby on Rails

Favor the use of sprintf and its alias format over the fairly cryptic String#% method

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad'%d %d' % [20, 10]# => '20 10'

# goodsprintf('%d %d', 20, 10)# => '20 10'

# goodsprintf('%{first} %{second}', first: 20, second: 10)# => '20 10'

format('%d %d', 20, 10)# => '20 10'

# goodformat('%{first} %{second}', first: 20, second: 10)# => '20 10'

Page 64: Ruby on Rails

Favor the use of Array#join over the fairly cryptic Array#* with [link] a string argument

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad%w(one two three) * ', '# => 'one, two, three'

# good%w(one two three).join(', ')# => 'one, two, three'

Page 65: Ruby on Rails

Use [*var] or Array() instead of explicit Array check, when dealing with a variable you want to treat as an Array, but you're not certain it's an array

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badpaths = [paths] unless paths.is_a? Arraypaths.each { |path| do_something(path) }

# good[*paths].each { |path| do_something(path) }

# good (and a bit more readable)Array(paths).each { |path| do_something(path) }

Page 66: Ruby on Rails

Use ranges or Comparable#between? instead of complex comparison logic when possible

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddo_something if x >= 1000 && x <= 2000

# gooddo_something if (1000..2000).include?(x)

# gooddo_something if x.between?(1000, 2000)

Page 67: Ruby on Rails

Favor the use of predicate methods to explicit comparisons with ==. Numeric comparisons are OK.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# goodif x.even?end

if x.odd?end

if x.nil?end

if x.zero?end

if x == 0end

# badif x % 2 == 0end

if x % 2 == 1end

if x == nilend

Page 68: Ruby on Rails

Don't do explicit non-nil checks unless you're dealing with boolean values.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddo_something if !something.nil?do_something if something != nil

# gooddo_something if something

# good - dealing with a booleandef value_set? !@some_boolean.nil?end

Page 69: Ruby on Rails

Never use END blocks. Use Kernel#at_exit instead

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badEND { puts 'Goodbye!' }

# goodat_exit { puts 'Goodbye!' }

Page 70: Ruby on Rails

Prefer a guard clause when you can assert invalid data.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# baddef compute_thing(thing) if thing[:foo] update_with_bar(thing) if thing[:foo][:bar] partial_compute(thing) else re_compute(thing) end endend

# gooddef compute_thing(thing) return unless thing[:foo] update_with_bar(thing[:foo]) return re_compute(thing) unless thing[:foo][:bar] partial_compute(thing)end

Page 71: Ruby on Rails

Prefer next in loops instead of conditional blocks.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad[0, 1, 2, 3].each do |item| if item > 1 puts item endend

# good[0, 1, 2, 3].each do |item| next unless item > 1 puts itemend

Page 72: Ruby on Rails

Naming

Page 73: Ruby on Rails

Name identifiers in English

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - identifier using non-ascii charactersзаплата = 1_000

# bad - identifier is a Bulgarian word, written with Latin letters (instead of Cyrillic)zaplata = 1_000

# goodsalary = 1_000

Page 74: Ruby on Rails

Use snake_case for symbols, methods and variables

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad:'some symbol':SomeSymbol:someSymbol

someVar = 5

def someMethod ...end

def SomeMethod...end

# good:some_symbol

def some_method ...end

Page 75: Ruby on Rails

Use CamelCase for classes and modules

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badclass Someclass ...end

class Some_Class ...end

class SomeXml ...end

# goodclass SomeClass ...end

class SomeXML ...end

Page 76: Ruby on Rails

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Use snake_case for naming files, e.g. hello_world.rb. [link]

Use snake_case for naming directories, e.g. lib/hello_world/hello_world.rb. [link]

Aim to have just a single class/module per source file. Name the file name as the class/module, but replacing CamelCase with snake_case. [link]

Use SCREAMING_SNAKE_CASE for other constants

Page 77: Ruby on Rails

The names of potentially dangerous methods should end with an exclamation mark if there exists a safe version of that dangerous method

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - there is no matching 'safe' methodclass Person def update! endend

# goodclass Person def update endend

# goodclass Person def update! end

def update endend

Page 78: Ruby on Rails

Define the non-bang (safe) method in terms of the bang (dangerous) one if possible.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Array def flatten_once! res = []

each do |e| [*e].each { |f| res << f } end

replace(res) end

def flatten_once dup.flatten_once! endend

Page 79: Ruby on Rails

Use two spaces per indentation level

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Prefer map over collect, find over detect, select over find_all, reduce over inject and size over length.

Don't use count as a substitute for size

Use flat_map instead of map + flatten

# badall_songs = users.map(&:songs).flatten.uniq

# goodall_songs = users.flat_map(&:songs).uniq

Page 80: Ruby on Rails

Use reverse_each instead of reverse.each. reverse_each doesn't do a new array allocation and that's a good thing.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badarray.reverse.each { ... }

# goodarray.reverse_each { ... }

Page 81: Ruby on Rails

Comments

Page 82: Ruby on Rails

Use two spaces per indentation level

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Good code is its own best documentation. As you're about to add a comment, ask yourself, "How can I improve the code so that this comment isn't needed?" Improve the code and then document it to make it even clearer. -- Steve McConnellWrite self-documenting code and ignore the rest of this section. Seriously! [link]

Write comments in English. [link]

Use one space between the leading # character of the comment and the text of the comment. [link]

Comments longer than a word are capitalized and use punctuation. Use one space after periods

Page 83: Ruby on Rails

Use two spaces per indentation level

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Good code is like a good joke - it needs no explanation. -- Russ Olsen

Avoid writing comments to explain bad code. Refactor the code to make it self-explanatory. (Do or do not - there is no try.

Page 84: Ruby on Rails

Comments Annotations

Page 85: Ruby on Rails

Guide

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Annotations should usually be written on the line immediately above the relevant code. [link]

The annotation keyword is followed by a colon and a space, then a note describing the problem. [link]

If multiple lines are required to describe the problem, subsequent lines should be indented two spaces after the #.def bar # FIXME: This has crashed occasionally since v3.2.1. It may # be related to the BarBazUtil upgrade. baz(:quux)end

Page 86: Ruby on Rails

Guide ...

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

In cases where the problem is so obvious that any documentation would be redundant, annotations may be left at the end of the offending line with no note. This usage should be the exception and not the rule

def bar sleep 100 # OPTIMIZEend

Page 87: Ruby on Rails

Guide ...

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

Use TODO to note missing features or functionality that should be added at a later date. [link]

Use FIXME to note broken code that needs to be fixed. [link]

Use OPTIMIZE to note slow or inefficient code that may cause performance problems. [link]

Use HACK to note code smells where questionable coding practices were used and should be refactored away. [link]

Use REVIEW to note anything that should be looked at to confirm it is working as intended. For example: REVIEW: Are we sure this is how the client does X currently? [link]

Use other custom annotation keywords if it feels appropriate, but be sure to document them in your project's README or similar.

Page 88: Ruby on Rails

Classes & Modules

Page 89: Ruby on Rails

Use a consistent structure in your class definitions.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Person # extend and include go first extend SomeModule include AnotherModule

# inner classes CustomErrorKlass = Class.new(StandardError)

# constants are next SOME_CONSTANT = 20

# afterwards we have attribute macros attr_reader :name

Page 90: Ruby on Rails

Continue ...

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# followed by other macros (if any) validates :name

# public class methods are next in line def self.some_method end

# followed by public instance methods def some_method end

# protected and private methods are grouped near the end protected

def some_protected_method end

private

def some_private_method endend

Page 91: Ruby on Rails

Don't nest multi line classes within classes

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad

# foo.rbclass Foo class Bar # 30 methods inside end

class Car # 20 methods inside end

# 30 methods insideend

# good

# foo.rbclass Foo # 30 methods insideend

# foo/bar.rbclass Foo class Bar # 30 methods inside endend

Page 92: Ruby on Rails

Prefer modules to classes with only class methods

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badclass SomeClass def self.some_method # body omitted end

def self.some_other_method endend

# goodmodule SomeClass module_function

def some_method # body omitted end

def some_other_method endend

Page 93: Ruby on Rails

Favor the use of module_function over extend self when you want to turn a module's instance methods into class methods

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badmodule Utilities extend self

def parse_something(string) # do stuff here end

def other_utility_method(number, string) # do some more stuff endend

# goodmodule Utilities module_function

def parse_something(string) # do stuff here end

def other_utility_method(number, string) # do some more stuff endend

Page 94: Ruby on Rails

Always supply a proper to_s method for classes that represent domain objects.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Person attr_reader :first_name, :last_name

def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end

def to_s "#{@first_name} #{@last_name}" endend

Page 95: Ruby on Rails

Use the attr family of functions to define trivial accessors or mutators

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badclass Person def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end

def first_name @first_name end

def last_name @last_name endend

# goodclass Person attr_reader :first_name, :last_name

def initialize(first_name, last_name) @first_name = first_name @last_name = last_name endend

Page 96: Ruby on Rails

Avoid the use of attr. Use attr_reader and attr_accessor instead

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# bad - creates a single attribute accessor (deprecated in 1.9)attr :something, trueattr :one, :two, :three # behaves as attr_reader

# goodattr_accessor :somethingattr_reader :one, :two, :three

Page 97: Ruby on Rails

Consider using Struct.new, which defines the trivial accessors, constructor and comparison operators for you

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# goodclass Person attr_accessor :first_name, :last_name

def initialize(first_name, last_name) @first_name = first_name @last_name = last_name endend

# betterPerson = Struct.new(:first_name, :last_name) doend

Page 98: Ruby on Rails

Consider adding factory methods to provide additional sensible ways to create instances of a particular class

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Person def self.create(options_hash) # body omitted endend

Page 99: Ruby on Rails

Prefer duck-typing over inheritance.

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# badclass Animal # abstract method def speak endend

# extend superclassclass Duck < Animal def speak puts 'Quack! Quack' endend

#bad# extend superclassclass Dog < Animal def speak puts 'Bau! Bau!' endend

Page 100: Ruby on Rails

Continue ...

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

# goodclass Duck def speak puts 'Quack! Quack' endend

class Dog def speak puts 'Bau! Bau!' endend

Page 101: Ruby on Rails

Avoid the usage of class (@@) variables due to their "nasty" behavior in inheritance

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class Parent @@class_var = 'parent'

def self.print_class_var puts @@class_var endend

class Child < Parent @@class_var = 'child'end

Parent.print_class_var # => will print "child"

Page 102: Ruby on Rails

Use def self.method to define singleton methods. This makes the code easier to refactor since the class name is not repeated

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

class TestClass # bad def TestClass.some_method # body omitted end

# good def self.some_other_method # body omitted end

# Also possible and convenient when you # have to define many singleton methods. class << self def first_method # body omitted end

def second_method_etc # body omitted end endend

Page 103: Ruby on Rails

References

Page 104: Ruby on Rails

Links

MASYMBOL TECHNOLOGIES – RUBY ON RAILS EXPERT

https://github.com/bbatsov/ruby-style-guidehttps://github.com/bbatsov/rubocop

Page 105: Ruby on Rails

THANK YOU FOR YOUR TIME

Masymbol Technologies Pvt Ltd