Slide 1

Slide 1 text

DICAS & TRUQUES RUBY Nando Vieira hellobits.com

Slide 2

Slide 2 text

@fnando

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

DICAS E TRUQUES CURIOSOS QUE PODEM SER ÚTEIS (OU NÃO) NO DIA-A-DIA.

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No Ruby, tudo é objeto (ou quase tudo).

Slide 9

Slide 9 text

Classes, módulos, números, strings, arrays, intervalos, símbolos, métodos, blocos, procs, nil, booleanos, hashes, expressões regulares.

Slide 10

Slide 10 text

O Ruby possui classes abertas que podem ser modi cadas a qualquer momento.

Slide 11

Slide 11 text

O Ruby é extremamente exível.

Slide 12

Slide 12 text

O Ruby é muito mais difícil do que as pessoas assumem.

Slide 13

Slide 13 text

DUCK TYPING, PROTOCOLOS E CONTRATOS

Slide 14

Slide 14 text

O Duck Typing permite estabelecer interfaces com um contrato informal.

Slide 15

Slide 15 text

class SimpleLogger def initialize(storage = []) unless storage.is_a?(Array) raise "you need to pass an array" end @storage = storage end def log(message) @storage << message end end

Slide 16

Slide 16 text

def initialize(storage = []) unless storage.is_a?(Array) raise "you need to pass an array" end @storage = storage end

Slide 17

Slide 17 text

def log(message) @storage << message end

Slide 18

Slide 18 text

@storage.<<(value)

Slide 19

Slide 19 text

File#<< String#<< Array#<< CSV#<< Set#<< IO#<< StringIO#<< Queue#<<

Slide 20

Slide 20 text

class SimpleLogger def initialize(storage = []) @storage = storage end def log(message) @storage << message end end

Slide 21

Slide 21 text

logger = SimpleLogger.new(nil) logger.log("Hello") #=> NoMethodError: undefined #=> method `<<' for nil:NilClass

Slide 22

Slide 22 text

O Ruby leva o Duck Typing por toda a linguagem, usando-o como protocolo de coersão.

Slide 23

Slide 23 text

#to_a #to_ary #to_d #to_f #to_i #to_proc #to_s

Slide 24

Slide 24 text

#to_proc

Slide 25

Slide 25 text

people = Person.all names = people.map do |person| person.name end

Slide 26

Slide 26 text

people = Person.all names = people.map(&:name)

Slide 27

Slide 27 text

&Na assinatura do método, converte bloco em Proc.

Slide 28

Slide 28 text

&Na chamada do método, converte Proc em bloco.

Slide 29

Slide 29 text

method(&object)

Slide 30

Slide 30 text

object.to_proc

Slide 31

Slide 31 text

people.map(&:name)

Slide 32

Slide 32 text

:name.to_proc #=> #

Slide 33

Slide 33 text

:name .to_proc .call(people.first)

Slide 34

Slide 34 text

class Symbol def to_proc proc do |target| target.public_send(self) end end end

Slide 35

Slide 35 text

PROCS & LAMBDAS

Slide 36

Slide 36 text

sum_proc = proc do |n1, n2| n1 + n2 end sum_lambda = lambda do |n1, n2| n1 + n2 end

Slide 37

Slide 37 text

sum_proc.class #=> Proc sum_lambda.class #=> Proc

Slide 38

Slide 38 text

sum_proc.lambda? #=> false sum_lambda.lambda? #=> true

Slide 39

Slide 39 text

sum_proc.parameters #=> [[:opt, :n1], [:opt, :n2]] sum_lambda.parameters #=> [[:req, :n1], [:req, :n2]]

Slide 40

Slide 40 text

Os parâmetros de um lambda são obrigatórios por padrão.

Slide 41

Slide 41 text

sum_proc.call #=> NoMethodError: undefined #=> method `+' for nil:NilClass sum_lambda.call #=> ArgumentError: wrong number #=> of arguments (0 for 2)

Slide 42

Slide 42 text

def proc_return proc { return "returning from proc" }.call "proc has finished" end puts proc_return #=> returning from proc

Slide 43

Slide 43 text

O retorno da proc, na verdade, faz com que o método pare de executar.

Slide 44

Slide 44 text

def lambda_return lambda { return "lambda: exiting method" }.call "lambda has finished" end puts lambda_return #=> lambda has finished

Slide 45

Slide 45 text

O retorno do lambda é auto- contido e não afeta o método.

Slide 46

Slide 46 text

O retorno de procs pode, inclusive, lançar exceções.

Slide 47

Slide 47 text

lambda { return "hello" }.call #=> hello proc { return "hello" }.call #=> LocalJumpError: unexpected return

Slide 48

Slide 48 text

proc { next "hello" this_wont_be_executed }.call

Slide 49

Slide 49 text

CALLABLE OBJECTS

Slide 50

Slide 50 text

hello = proc do |name| puts "hello, #{name}!" end

Slide 51

Slide 51 text

hello.call("John")

Slide 52

Slide 52 text

hello["John"]

Slide 53

Slide 53 text

hello.("John")

Slide 54

Slide 54 text

hello === "John"

Slide 55

Slide 55 text

object = 9 multiple_of_3 = proc do |n| n.modulo(3).zero? end

Slide 56

Slide 56 text

case object when multiple_of_3 "is multiple of 3" when Array "is a array" when /@/ "contains at-sign" else "couldn't understand" end

Slide 57

Slide 57 text

Proc#=== Regexp#=== Module#===

Slide 58

Slide 58 text

Array === [] #=> true multiple_of_3 === 9 #=> true /@/ === "[email protected]" #=> true

Slide 59

Slide 59 text

Object#method Module#instance_method

Slide 60

Slide 60 text

Métodos não são objetos de primeira classe.

Slide 61

Slide 61 text

Estendendo métodos sem ter que criar uma nova classe.

Slide 62

Slide 62 text

class Hellobits def cool # do something end end

Slide 63

Slide 63 text

class Hellobits alias_method :original_cool, :cool def cool # do something before original_cool # do something after end end

Slide 64

Slide 64 text

class Hellobits cool_method = instance_method(:cool) define_method :cool do # do something before cool_method.bind(self).call # do something after end end

Slide 65

Slide 65 text

SPLATTING

Slide 66

Slide 66 text

*args

Slide 67

Slide 67 text

class Module def attr_dsl(*args) args.each do |arg| # do something end end end

Slide 68

Slide 68 text

class Settings names = %w[path size locale] attr_dsl *names end

Slide 69

Slide 69 text

def coords(*) # do something -23.598737, -46.674685 end latitude, longitude = coords

Slide 70

Slide 70 text

a, b, c, d = [1, 2, 3, 4]

Slide 71

Slide 71 text

a, b, c, d = 1, 2, 3, 4

Slide 72

Slide 72 text

a, b, *c = 1, 2, 3, 4 #=> a=1, b=2, c=[3,4]

Slide 73

Slide 73 text

a, *b, c = 1, 2, 3, 4 #=> a=1, b=[2,3], c=4

Slide 74

Slide 74 text

numbers = [1, 2, 3] more_numbers = [*numbers, 4, 5, 6] #=> [1, 2, 3, 4, 5, 6]

Slide 75

Slide 75 text

(1..10).to_a.sample [*1..10].sample

Slide 76

Slide 76 text

date = "2012-07-10" regex = /(\d+)-(\d+)-(\d+)/ _, year, month, day = *date.match(regex)

Slide 77

Slide 77 text

class Sample def to_a [1, 2, 3] end end a, b, c = *Sample.new

Slide 78

Slide 78 text

MAIS SOBRE ATRIBUIÇÕES

Slide 79

Slide 79 text

path = nil if !path path = "/some/default/path" end

Slide 80

Slide 80 text

path = nil path = "/some/path" unless path

Slide 81

Slide 81 text

path = nil path ||= "/some/path"

Slide 82

Slide 82 text

variable || variable = expr

Slide 83

Slide 83 text

html = nil if html html << "

Hello

" end

Slide 84

Slide 84 text

html = nil html << "

Hello

" if html

Slide 85

Slide 85 text

html = nil html &&= html << "

Hello

"

Slide 86

Slide 86 text

variable && variable = expr

Slide 87

Slide 87 text

DE ONDE VEM ESSE MÉTODO

Slide 88

Slide 88 text

user = User.new user.methods #=> [:name, :age, ...]

Slide 89

Slide 89 text

user.method(:name)

Slide 90

Slide 90 text

Method#arity Method#name Method#owner Method#parameters Method#source_location

Slide 91

Slide 91 text

user.method(:name) .source_location #=> ["/tmp/user.rb", 2]

Slide 92

Slide 92 text

EXPRESSÕES REGULARES

Slide 93

Slide 93 text

person = "John " regex = /(.*?) <(.*?)>/ _, name, email = *person.match(regex)

Slide 94

Slide 94 text

person[/(.*?) <(.*?)>/, 1] person[/(.*?) <(.*?)>/, 2]

Slide 95

Slide 95 text

person .match(/(?.*?) <(?.*?)>/)

Slide 96

Slide 96 text

match.names #=> ["name", "email"] match.captures #=> ["John Doe", "[email protected]"] match[:name] #=> "John Doe" match[:email] #=> "[email protected]"

Slide 97

Slide 97 text

ENUMERATORS

Slide 98

Slide 98 text

names.each(&block) names.each_with_index(&block)

Slide 99

Slide 99 text

names.each_with_index do |name, index| puts "#{index + 10}. #{name}" end

Slide 100

Slide 100 text

names .each .with_index(10) do |name, index| puts "#{index}. #{name}" end

Slide 101

Slide 101 text

names .sort .uniq .each .with_index(10, &block)

Slide 102

Slide 102 text

HASHES & ENUMERATORS

Slide 103

Slide 103 text

hash.each do |key, value| # do something end

Slide 104

Slide 104 text

hash .each .with_index(10) do |pair, index| name, value = pair # do something end

Slide 105

Slide 105 text

hash .each .with_index(10) do |(name, value), index| # do something end

Slide 106

Slide 106 text

SYMBOLS

Slide 107

Slide 107 text

:name

Slide 108

Slide 108 text

:"full name"

Slide 109

Slide 109 text

:"hello #{name}"

Slide 110

Slide 110 text

E PARA FINALIZAR...

Slide 111

Slide 111 text

O Ruby possui uma série de truques que podem ajudar bastante.

Slide 112

Slide 112 text

Mais do que saber usar, você precisa saber quando usar.

Slide 113

Slide 113 text

Sintaxes exotéricas serão mais difíceis de entender.

Slide 114

Slide 114 text

Conheça Ruby. Todo o resto vem de graça.

Slide 115

Slide 115 text

OBRIGADO!