Ruby and Rails

Good practices for having readable code

Nathaly Villamor

What is Ruby?

  • is a programming language
  • is objected-oriented
  • powerful string operations and regular expressions
  • quick and easy

What are good practices?

1. Do not use :: to define methods

class Foo
  def self::some_method
  end
end
class Foo
  def self.some_method
  end
end
def some_method()
  # body omitted
end
def some_method
  # body omitted
end

2. Omit the parentheses when the method doesn't accept any parameters.

def some_method_with_parameters param1, param2
  # body omitted
end
def some_method_with_parameters(param1, param2)
  # body omitted
end

3. Use def with parentheses when there are parameters.

  attr_reader(:name, :age)
  attr_reader :name, :age

4. Methods that are called in the top of the sheet

a, b, c, d = 'foo', 'bar', 'baz', 'foobar'
a = 'foo'
b = 'bar'
c = 'baz'
d = 'foobar'

5. Parallel assignment is less readable than separate assignment

for elem in arr do
  puts elem
end
arr.each { |elem| puts elem }

6. Do not use for, is better each

class HomeController < ApplicationController
    def index
        # bad
        @recent_books = Book.where("books.published_at > ?",  1.week.ago).order("books.published_at DESC")
    end
end
class HomeController < ApplicationController
    def index
        # good
        @recent_books = Book.recent.published_desc 
        # 'recent' and 'published_desc' are scopes defined in Book model
    end
end

7. Do not use default scopes, is better custom scopes

Rails

#bad
def search
  params.except!(:action, :controller)
  @search = User.search(params)
  render "search"
end

# better
def search
  @search = User.search(search_params)
  render "search"
end

private

def search_params
  # params.except(:action, :controller)
  params.permit(:user_id, :name)
end

8. Do not modify the params , is better sanitize them

Rails

#bad
begin
  foo
rescue Exception => e
  logger.warn "Unable to foo, will ignore: #{e}"
end

#good

begin
  foo
rescue => e
  logger.warn "Unable to foo, will ignore: #{e}"
end

# also good
begin
  # an exception occurs here

rescue StandardError => e
   logger.warn "Unable to foo, will ignore: #{e}"
end

9. Do not use Exception, is better specific exceptions

Let's discuss

 

What's better?

def foo
  begin
    # main logic goes here
  rescue
    # failure handling goes here
  end
end
def foo
  # main logic goes here
rescue
  # failure handling goes here
end

What's better?

{ a: 1, 'b' => 2 }
{ :a => 1, 'b' => 2 }

What's better?

hash.key?(:test)
hash.value?(value)
hash.has_key?(:test)
hash.has_value?(value)

What's better?

[*paths].each { |path| do_something(path) }
paths = [paths] unless paths.is_a? Array
paths.each { |path| do_something(path) }
Array(paths).each { |path| do_something(path) }

Bonus

unless !holi
  #do something
end
if holi.present?
  #do something
end

Rails

References:

  • Ruby style guide -> bbatsov
  • RuboCop -> bbatsov
  • https://emilioforrer.gitbooks.io/buenas-practicas-de-programacion-en-rails/codigo_y_sintaxis/colecciones.html

Thank you

Made with Slides.com