/Documentation

This repository contains the documentation of this team.

STYLE SHEET

In this document you will see how to program using pre set technics about the code, organization of files and more.

1. Indentation and Spacing

  • Indentations levels are defined with a hard tab, which size is of four Spacings.
#right
def enterprise_group_ranking
    @quantity = params[:sanctions_count]
    @enterprises = Enterprise.where(sanctions_count: @quantity).paginate(:page => params[:page], :per_page => 10)
end
  • There are only one statement per line.
# wrong
puts 'testcase'; # superfluous semicolon

puts 'test'; puts 'case' # two expressions on the same line

#right
puts 'testcase'

puts 'test'
puts 'case'
  • Classes with no body definitions are not defined in a single-line format.
#wrong
PaymentClass = Class.new(Payment)

#right
class Payment < ActiveRecord::Base
    #content starts here
end
  • Methods also must not be defined in a single-line format.
#wrong
def refresh!; something; something_else; end

#right
def refresh!
    s = SanctionType.find_by_description(self.description)
end
  • Spaces are used after:
    • commas
    • colons
    • operators
    • semicolons
    • around {, [, ( and before }, ] and )
    • Spaces are also used before operators.
    • The exception regarding operators is the exponent operator.
    • No spaces are used after !.
#wrong
array = [element1,element2,element3]

puts "(I'm a string)"
puts "[I'm a string]"
puts "{I'm a string}"

range1 = ( 1 .. 10 )

exponent_variable = 2 ** 5

false_boolean = ! true

#right
array = [ element1, element2, element3 ]

puts "( I'm a word )"
puts "[ I'm a string ]"
puts "{ I'm a string }"

range1 = (1..10)

exponent_variable = 2**5

false_boolean = !true
  • No spaces are used inside range operators.
  • The when statement is indented one level deeper than case statement.
#wrong
case
when user.login == ''
  puts 'Not again!'
when user.login == 'user_login'
  puts 'Good!'
when Time.now.hour == 'a_very_long_long_long_login'
  puts 'too long bro!'
else
  user.login
end

#right
case
    when user.login == ''
        puts 'Not again!'
    when user.login == 'user_login'
        puts 'Good!'
    when Time.now.hour == 'a_very_long_long_long_login'
        puts 'too long bro!'
    else
        user.login
end
  • Methods are separated between them with empty lines. There are no empty lines between the method definition and its scope.
#wrong
def enterprise_group_ranking

  @quantity = params[:sanctions_count]
  @enterprises = Enterprise.where(sanctions_count: @quantity).paginate(:page => params[:page], :per_page => 10)

end
def payment_group_ranking

  @quantity = params[:payments_count]
  @enterprises = Enterprise.where(payments_count: @quantity).paginate(:page => params[:page], :per_page => 10)

end

#right
def enterprise_group_ranking
    @quantity = params[:sanctions_count]
    @enterprises = Enterprise.where(sanctions_count: @quantity).paginate(:page => params[:page], :per_page => 10)
end

def payment_group_ranking
    @quantity = params[:payments_count]
    @enterprises = Enterprise.where(payments_count: @quantity).paginate(:page => params[:page], :per_page => 10)
end
  • Parameters of method calls, when spamming more than one line, are indented.
#wrong
def a_simple_method ( argument_one, argument_two, argument_three, argument_four,argument_five, argument_six, argument_seven)
    #content starts here
end

#right
def a_simple_method ( argument_one,
                      argument_two,
                      argument_three,
                      argument_four,
                      argument_five,
                      argument_six,
                      argument_seven )
    #content starts here
end
  • Each line is limited to 80 characters.
#wrong
long_variable = "abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde"

#right
long_variable = "abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeab"
  • Align the element of an array that appears in more than one line.
#wrong
a_long_array = [ element1, element2, element3, element4, element5, element6,
element7, element8, element9, element10, element11 ]

#right
a_long_array = [ element1, element2, element3, element4, element5, element6,
                 element7, element8, element9, element10, element11 ]

2. Syntax

  • Every variable must be initialized.
#wrong
user_name
user_age

#right
user_name = ""
user_age = 0
  • :: is used only for constants and constructors. Not for regular method invocation.
#wrong
PaymentClass::payment_class_method

#right
PaymentClass.payment_class_method
EnterpriseModule::EnterpriseSomeClass::SOME_CONST
  • Optional parameters are defined at the end of the parameters list.

  • each must be used instead of for, unless it is unavoidable.

#wrong
def last_sanction
    sanctions = [ "section1","section2","section3" ]

    for sanction in sanctions
        puts sanction
    end
end

#right
def last_sanction
    sanctions = [ "section1","section2","section3" ]

    sanctions.each do |sanction|
        puts sanction
    end
end
  • Use if/else statement to express conditions. The condition of a if/else statement is written on the same line and between parenthesis, and the body of an if/else statement is closed by {}. Opening braces are written on the same line.
#wrong
if 5 > 4
    puts "It's true"
end

#right
if ( 5 > 4 ){
    puts "It's true"
}
  • Every if statement must have an additional else statement.
#wrong
user_name = "Bob"

if(user_name != nil){
    puts user_name
}

#right
if( user_name != nil ){
    puts user_name
}
else{
    #nothing to do
}
  • Only one expression per line is used in the body of a constructor, like if/else. comment: # (* The nested form if x;... must not be used.)
  • Ternary Operator ?: must not be used. if/then/else/end must be used instead.
  • The operator ! must be used instead of not.
  • The operators && and || must not be used. Instead, are used the keywords and and or.
#wrong
if ( 5 > 4 && 6 > 5 ){
    puts "It's true"
}

if ( 5 > 4 || 6 > 5 ){
    puts "It's true"
}

#right

if ( 5 > 4 and 6 > 5 ){
    puts "It's true"
}

if ( 5 > 4 or 6 > 5 ){
    puts "It's true"
}
  • unless must not be used with else. if must be used instead.

  • Parenthesis around parameters of methods that are part of an internal DSL, such as Rake, Rails or RSpec, methods that have a keyword status in Ruby, like attr_reader or puts, and attribute access methods, must be omitted. In any other methods, parenthesis must be used around parameters.

#wrong
class Payment
    attr_reader( :name, :date )
    # content starts here
end

#right
class Payment
    attr_reader :value, :date
    # content starts here
end

3. Naming

  • Names are defined in english.
  • snake_case is used for:
    • symbols
    • methods
    • variables
    • naming files
    • naming directories
  #wrong
def LastPayment
    puts paymentVariable
end

#right
def last_payment
    puts payment_variable
end
#wrong
sanctioType.rb
#right
sanction_type.rb
#wrong
App/allModels/sanction_type.rb

#right
app/all_models/sanction_type.rb
  • camelCase is used for classes.
#wrong
class User_controller < ActiveRecord::Base
    #class content
end

#right
class UserController < ActiveRecord::Base
    #class content
end
  • SCREAMING_SNAKE_CASE is used for constants and global variables.
#wrong
constant_sanction = "I'm a constant"

#right
CONSTANT_SANCTION = "I'm a constant"

4. Comments

  • Use block comments instead of single line comments.
#wrong
=begin
comment line
another comment line
=end

#right
# good
# Comment line.
# Another comment line.
  • Comments are written in english.
  • Comments longer than one word are Capitalized, and end with a period. A space is used after a period.
#wrong

# i'm a long comment, you should've notice that my lenght is being
# greater quickly

#right

# I'm a long comment, you should've notice that my lenght is being
# Greater quickly.

5. Classes and Modules

  • Classes must have a consistent structure. The class definition is followed by, in this order: extendand include, inner classes, constants, attribute macros, other macros (if any), public class methods, initializations, public instance methods, and, near the end, protected and private methods.
class Payment
    # 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

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

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

    # initialization goes between class methods and other instance methods
    def initialize
        #content starts here
    end

    # followed by other public instance methods
    def some_method
        #content starts here
    end

    # protected and private methods are grouped near the end
    protected

    def some_protected_method
        #content starts here
    end

    private

    def some_private_method
        #content starts here
    end

end
  • Multi-line classes must not be nested. Instead, each class must have its own file.
# wrong

# foo.rb
class User
    class Payment
        # 30 methods inside
    end

    class State
        # 20 methods inside
    end
  # 30 methods inside
end

# right

# foo.rb
class User
    # 30 methods inside
end

# foo/bar.rb
class User
    class Payment
        # 30 methods inside
    end
end

# foo/car.rb
class User
    class State
        # 20 methods inside
    end
end
  • Modules should be preferred instead of classes, if they only have class methods. A class should only be created if it makes sense to do so.
# wrong
class UserClass
    def self.some_method
        # content starts here
    end

    def self.some_other_method
        #content starts here
    end
end

# right
module SomeModule
    module_function

    def some_method
        #content starts here
    end

    def some_other_method
        #content starts here
    end
end
  • The attr functions must be used to define trivial accessors or mutators.
#wrong
class Person
    def initialize(value, date)
        @date = date
        @date = date
    end

    def value
        @value
    end

    def date
        @date
    end
end

#right
class Payment
    attr_reader :value, :date

    def initialize(value, date)
        @value = value
        @date = date
    end
end
  • attr_reader and attr_accessor must be used instead of attr.
# wrong
attr :value, true
attr :one, :two, :three

# right
attr_accessor :value
attr_reader :one, :two, :three
  • Class variables @@ must not be used.

  • Visibility levels to methods, like public, protected, private, must be used properly, depending on the method and its functionality and objective.

  • The visibility method must be indented on the same level as the method they apply to. One blank line must be used above and below the visibility level.

class PaymentClass
      def public_method
            #content starts here
      end

      private

      def another_private_method
            #content starts here
      end
end
  • self.method must be used to define class methods.
Class User
    self.user_self_method
        #content starts here
    end
end

6. Exceptions

  • Exceptions are signaled with the fail method. The raise method must be used only when purposely raising the exception.

  • RuntimeError must not be explicitly specified in fail/raise.

  • fail/raise must not be used with an exception instance, instead being used with an exception and a message as arguments.

# wrong
fail PaymentException.new('message')
# Note that there is no way to do `fail SomeException.new('message'), backtrace`.

# right
fail PaymentException, 'message'
# Consistent with `fail SomeException, 'message', ba´cktrace`.

7. Collections

  • Array and hash creation notation must be used in its literal form.
# wrong
array = %w(poor rich milionaire)

# right
array = [ 'poor',  'rich',  'milionaire' ]
  • Comma after the last item of an array or hash must not be used.
# wrong
array = [ 'poor',  'rich',  'milionaire
', ]

# right
array = [ 'poor',  'rich',  'milionaire' ]
  • first and last must be used accessing the first or last item of an array or hash, instead of [0] or [-1].
#wrong
First_element = array[0]

#right
First_element = array.first
  • Symbols must be used instead of strings as hash keys, unless for some reason unavoidable.
# wrong
hash = { 'key1' => 1, 'key2' => 2, 'key3' => 3 }

# right
hash = { key1: 1, key2: 2, key3: 3 }
  • Hash keys must follow the Ruby 1.9 hash literal syntax , being composed of the symbol name, followed by a colon and the key value.
#wrong
hash = { :key1 => 1, :key2 => 2, :key3 => 3 }

# right
hash = { key1: 1, key2: 2, key3: 3 }
  • If there is a key that is not a symbol in a hash, the hash rocket syntax must be used for all keys instead of the Ruby 1.9 hash literal syntax.
#wrong
{ key_a: 1, 'key_b': 2 }

#right
{ :key_a => 1, 'key_b' => 2 }

8. References

    https://github.com/bbatsov/rails-style-guide