Skip to content

johnvoloski/ruby

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

58 Commits

Repository files navigation

RUBY

Referência técnica da linguagem Ruby, baseado no material preparado por John Voloski (johnvoloski).

Introdução:

John Voloski:

  • @johnvoloski
    • github
    • bitbucket
    • gmail.com
    • cwi.com.br
  • Projeto Atual ( Fábrica RoR )

História do Ruby:

  • Yukihiro "Matz" Matsumoto
  • Se tornou pública em 1995
  • Ganhou muita popularidade com o Rails

Características:

  • Open Source
  • Orientada a Objetos
  • Blocos de Código
  • Mixins
  • RubyGems
  • Linguagem Interpretada

Interpretadores:

  • MRI
  • YARV
  • JRuby
  • Rubinius
  • MagLev
  • MacRuby

Console:

  • irb

Editores:

Links:

O que é uma Gem?

Uma "RubyGem" ou simplesmente "Gem" é uma biblioteca, um conjunto de arquivos Ruby reusáveis, etiquetada com um nome e uma versão (via um arquivo chamado de "gemspec").

Gems "Famosas":

Quem usa:

RubyGems:

  • RubyGems Commands
  • gem dependency GEMNAME - Mostra as dependências da gem instalada.
  • gem fetch GEMNAME - Baixa a gem e coloca no diretório atual.
  • gem help - Ajuda
  • gem install GEMNAME - Instala uma gem.
  • gem list GEMNAME - Lista as gems que começam com a GEMNAME
  • gem outdated - Exibe todas as gems que necessitam de update.
  • gem push - Sobe uma gem para o rubygems
  • gem search GEMNAME - Pesquisa uma gem no rubygems com a GEMNAME.
  • gem uninstall GEMNAME - Desinstala uma gem.
  • gem update GEMNAME - Atualiza a gem para a última versão.
  • gem yank GEMNAME -v VERSION - Remove uma versão da gem no rubygems.

Bundler:

É um gerenciador de gems da aplicação. Gerando uma lista de gems ele se encarrega de instalar, verificar versões e compatibilidades, após instaladas o bundler ajuda a atualizar quando tiver versões novas disponíveis, e registra as versões instaladas pra que se possa replicar exatamente as mesmas versões em diversas máquinas.

GemfileGemfile.lock

Rake:

É um automatizador de tarefas, você consegue criar tarefas utilizando a sintaxe do ruby como por exemplo publicar algo em um ssh ou ftp automaticamente.

# Rakefiletask:ftpdo ... end

Rakefile

Instalação:

Hospedagem:

Integração Contínua:

Gerênciadores de Versões Ruby:

Comentários:

# SpongeBob SquarePants.=begin SpongeBob SquarePants. Patrick isn't SquarePants.=end

Tipos de Dados:

True, False e Nil:

True representa o verdadeiro, False o falso e nil representa a abstenção de valor. Qualquer valor sem ser False e Nil é True.

putstrue.class# TrueClassputsfalse.class# FalseClassputsnil.class# NilClass

Numbers:

Integer:

Pode ser utilizado o _ para melhor visualização.

puts1_000_000_00# 100000000puts1_000_000_00.class# Fixnum
Fixnum:

São inteiros que se encaixam dentro de 31 bits então sua instância é um Fixnum.

puts999999999999999999.class# Fixnum
Bignum:

São inteiros que se encaixam acima de 31 bits então sua instância é um Bignum.

puts9999999999999999999.class# Bignum

Float:

São números que utilizam pontos flutuantes, sua instância é um Float.

99.99.class# Float

Rational:

São números racionais, sua instância é um Rational.

putsRational(8/4).class# Rational

Strings:

Aspas Simples:

puts'Sou uma string com aspas simples e com instância String'.class# Stringputs'Sou uma string com aspas simples'# Sou uma string com aspas simplesputs'Sou uma string \' com um "escape"'# Sou uma string ' com um "escape"puts'Sou uma string quebrada' \ 'em multiplas linhas' \ 'não somente em uma'# Sou uma string quebrada em multiplas linhas não somente em uma

Aspas Duplas:

puts"Sou uma string com aspas duplas e com instância String".class# Stringputs"Sou uma string com aspas duplas"# Sou uma string com aspas duplas

Interpolações em string são feitas através do #{}:

adjective='SquarePants'puts"SpongeBob #{adjective}"# SpongeBob SquarePants

Symbols:

Um símbolo é um identificador único no ruby. O símbolo referencia ele mesmo. Um símbolo tem uma comparação muito mais rápida que uma string. Símbolos são ideais para definerem uma chave dentro de um hash, pois é um valor que não será alterado.

friends=['SpongeBob','Patrick']putsfriends# ["SpongeBob", "Patrick"]friends=[:SpongeBob,:Patrick]putsfriends# [:SpongeBob, :Patrick]

Arrays:

Um array é uma sequência de valores acessíveis pela sua posição ou indíce. Em ruby o valor do primeiro indíce é 0.

puts[1,2,3,4]# [1, 2, 3, 4]putsArray.new(4)# [nil, nil, nil, nil]

Hashes:

Um hash em ruby é composto por objetos formados por chave => valor.

sb={'SpongeBob'=>'SquarePants'}putssb['SpongeBob']# SquarePantssb={:SpongeBob=>'SquarePants'}putssb[:SpongeBob]# SquarePantssb={SpongeBob: 'SquarePants'}putssb[:SpongeBob]# SquarePants

Ranges:

O range representa o intervalo entre um início e um final.

# Irá gerar um intervalo de 1 à 10 incluindo o 10.puts1..10# 1..10# Irá gerar um intervalo de 1 à 10 excluíndo o 10.puts1...10# 1...10# Pode ser usado com strings também.puts'a'..'f'# 'a'..'f'

Expressões Regulares:

  • Em ruby as expressões regulares são representadas por /
puts'SpongeBob'.gsub(/[aeiou]/,'')# SpngBb

Expressões e Operadores:

Variáveis Globais:

  • Variáveis globais começam com $. Não inicializadas seu valor padrão é nil.
  • Elas são visíveis de qualquer lugar.
$global_variable =0classHelloWorldOnedefincrement $global_variable += 1enddefoutputputs $global_variable endendclassHelloWorldTwodefoutputputs $global_variable endendclassOne=HelloWorldOne.newclassOne.incrementclassOne.output# 1classTwo=HelloWorldTwo.newclassOne.incrementclassTwo.output# 2

Variáveis de Instância:

  • Variáveis de instância começam com @. Não inicializadas seu valor padrão é nil.
  • Elas são visíveis apenas dentro da instância, compartilhada entre os métodos de instância.
  • Elas podem ser acessadas externamente criando um attr.
classHelloWorldOnedefinitialize(value)@instance_variable=valueenddefoutputputs@instance_variableendendclassHelloWorldTwodefinitialize(value)@instance_variable=valueenddefoutputputs@instance_variableendendHelloWorldOne.new("SpongeBob SquarePants").output# SpongeBob SquarePantsHelloWorldTwo.new("Patrick").output# Patrick

Variáveis de Classe:

  • Variáveis de classe começam com @@. Devem ser inicializadas.
  • Elas são visíveis e compartilhadas entre métodos de classe, métodos de instância e classes do mesmo tipo.
  • Elas são encapsuladas, só podem ser acessadas e usadas na implementação e não de fora.
classHelloWorldOne@@class_variable=''defassign_variable(value)@@class_variable=valueenddefoutputputs@@class_variableendendone=HelloWorldOne.newone.assign_variable("SpongeBob SquarePants")one.output# SpongeBob SquarePantstwo=HelloWorldOne.newtwo.output# SpongeBob SquarePants

Variáveis Locais:

  • Variáveis locais começam com uma letra minúscula ou _ .
  • O escopo de uma variável local varia de classe, módulo, método ou a abertura e fechamento de um bloco, que corresponde ao final de seu ciclo.
classHelloWorlddefinitialize(value)putsvalueendendHelloWorld.new('SpongeBob SquarePants')# SpongeBob SquarePants

Constants:

  • Constantes começam com uma letra maiúscula.
  • Constantes podem ser visualizadas internamente de uma classe ou módulo, apenas pelo seu nome, ou externamente através do seu módulo/classe mais o seu nome.
classHelloWorldHELLO_WORLD='Hello SpongeBob SquarePants'defoutputHELLO_WORLDendendputsHelloWorld.new.output# Hello SpongeBob SquarePantsputsHelloWorld::HELLO_WORLD# Hello SpongeBob SquarePants

Operadores:

Aritimético:

  • +
# Soma o valor da variável a com o valor da variável b e returna o resultado.a=10b=20putsa + b# 30
  • -
# Subtrai da variável a o valor da váriavel b e returna o resultado.a=10b=20putsa - b# -10
  • *
# Multiplica o valor da variável a com o valor da variável b e retorna o resultado.a=10b=20putsa * b# 200
  • /
# Divide o valor da variável b por o valor da variável a e retorna o resultado.a=10b=20putsb / a# 2
  • %
# Divide o valor da váriavel b por o valor da variável a e retorna o quociente da divisão.a=10b=20putsb % a# 0
  • **
# Executa o cálculo exponencial sobre o valor da variável a quando o valor de seu expoente é o valor da variável b e retorna o resultado.a=10b=2putsa**b# 100

Comparação:

  • ==
# Verifica se o valor da variável a é igual ao valor da variável b, se sim retorna true.a=10b=20puts(a == b)# false
  • !=
# Verifica se o valor da váriavel a é diferente do valor da variável b, se sim retorna true.a=10b=20puts(a != b)# true
  • >
# Verifica se o valor da variável a é maior que o valor da variável b, se sim retorna true.a=10b=20puts(a > b)# false
  • <
# Verifica se o valor da variável a é menor que o valor da variável b, se sim retorna true.a=10b=20puts(a < b)# true
  • >=
# Verifica se o valor da variável a é maior ou igual ao valor da variável b, se sim retorna true.a=10b=20puts(a >= b)# false
  • <=
# Verifica se o valor da variável a é menor ou igual ao valor da variável b, se sim retorna true.a=10b=20puts(a <= b)# true
  • <=>
# Verifica se o valor da variável a é igual ao valor da váriavel b, então retorna 0, verifica se o valor da variável a é maior que o valor da váriavel b, então retorna 1, e verifica se o valor da variável a é menor que o valor da variável b, então retorna -1.a=10b=20puts(a <=> b)# -1
  • ===
# É um sinônimo do operador ==, e muda dependendo da implementação do seu contexto.a=10putsa === 10# trueputsObject === a# trueputsFixnum === a# trueputsInteger === a# trueputs(1..10) === a# true
  • .eql?
# Verifica se o valor da variável a é igual ao valor da variável b, mas muda dependendo do seu contexto.a=10b=10.0putsa == b# true# a.class(Fixnum) and b.class(Float)putsa.eql?(b)# false
  • .equal?
# Compara se os mesmos apontam para o mesmo objeto em memória.a=10a.__id__21b=10b.__id__21putsa.equal?(b)truea="word"a.__id__87897809b="word"b.__id__87893729putsa.equal?(b)false

Atribuição:

  • =
# Atruibui o valor da variável a para a váriavel b.a=10b=aputsb# 10
  • +=
# Atribui somando o valor da variável a por o valor da váriavel b.a=10b=10b += aputsb# 20
  • -=
# Atribui subtraindo o valor da variável a por o valor da váriavel b.a=10b=10b -= aputsb# 0
  • *=
# Atribui multiplicando o valor da variável a por o valor da váriavel b.a=10b=10b *= aputsb# 100
  • /=
# Atribui dividindo o valor da variável a por o valor da váriavel b.a=10b=10b /= aputsb# 1
  • %=
# Atribui o quociente da divisão do valor da variável a por o valor da váriavel b.a=10b=10b %= aputsb# 0
  • **=
# Atribui calculando o valor exponencial do valor da variável a por o valor da váriavel b.a=10b=2b **= aputsb# 1024

Atribuição Múltipla:

# Atribui paralelizadamente valores à variáveis seguindo sua ordem de definição.a,b,c=10,20,30

Lógico:

  • and ou &&
# Se o valor da variável a e o valor da variável b forem verdadeiros, a condição é verdadeira.a=trueb=trueputs'True'ifaandb# Trueputs'True'ifa && b# True
  • or ou ||
# Se o valor da variável a ou o valor da variável b forem verdadeiros, a condição é verdadeira.a=trueb=falseputs'True'ifaorb# Trueputs'True'ifa || b# True
  • ! ou not
# Se o valor da variável a e o valor da variável b forem falsos, a condição é verdadeira.a=falseb=falseputs'True'if !(a && b)# Trueputs'True'if not(a && b)# True

Ternário:

  • ?:
# Cria uma expressão condicional.condition=falseputsconditidion ? true : false# true

Intervalo:

  • ..
# Cria um intervalo entre o ponto de partida e o ponto de chegada incluido ele.puts(1..10).to_a# 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
  • ...
# Cria um intervalo entre o ponto de partida e o ponto de chegada excluíndo ele.puts(1...10).to_a# 1, 2, 3, 4, 5, 6, 7, 8, 9

Controle de Estruturas e Afirmação:

Condicionais:

if, else afirmação:

conditional=1ifconditional > 2puts'conditional is greater than 2'elsifconditional <= 2 && conditional != 0puts'conditional is 1'elseputs'I can`t guess the number'end# conditional is 1

if modificador:

conditional=trueputs'Is true.'ifconditional# Is true

unless afirmação:

conditional=1unlessconditional > 2puts'conditional is less than 2'elseputs'conditional is greater than 2'end# conditional is less than 2

unless modificador:

conditional=falseputs'Is false.'unlessconditional# Is false

case afirmação:

conditional=10caseconditionalwhen1puts'Is 1.'when2 .. 5puts'Is between 2 and 5'when6 .. 9puts'Is between 6 and 9'when10puts'is 10'elseputs'I can`t guess the number'end# is 10

Laços

While afirmação:

a=0b=5whilea < bdoputsaa += 1end# 0, 1, 2, 3, 4

While modificador:

a=0b=5beginputsaa += 1endwhilea < b# 0, 1, 2, 3, 4

Until afirmação:

a=0b=5untila > bdoputsaa += 1end# 0, 1, 2, 3, 4, 5

Until modificador:

a=0b=5beginputsaa += 1enduntila > b# 0, 1, 2, 3, 4, 5

For:

forain0..5putsaend# 0, 1, 2, 3, 4, 5

Blocos:

Os blocks assim como é definido são blocos de códigos formados por delimitadores {... } ou do ... end, a convensão que usamos é {... } para uma linha e do ... end para mais de uma linha. O bloco serve para armazenar uma implementação que for desejada, e será executada em um certo momento, com seu pŕoprio escopo. Blocos só podem ser usados com métodos. Eles podem ser executados atráves do & chamando na implementação block.call, ou também através do yield, o yield tem como função executar um bloco anônimo sem precisar ser especificado no método.

classSpongeBobdefis_squarepants?(&block)block.callenddefi_live_in_ocean?yieldendendSpongeBob.new.is_squarepants?{putstrue}# trueSpongeBob.new.i_live_in_ocean?doputstrueend# true

Alteradores de Controle de Fluxo:

Return

forain0..5returnaifa > 2putsaend# 0, 1, 2

Break:

forain0..5breakifa > 2putsaend# 0, 1, 2

Next:

forain0..5nextifa < 2putsaend# 2, 3, 4, 5

Redo:

forain0..5putsa redo ifa < 2end# Loop infinito

Retry:

a=0begina += 1raiseNoMethodErrorrescueputsaretryend# Retry infinito

Exceções e Tratamentos:

Hierarquia da Classe de Exceção do Ruby:

  • Object
    • Exception
      • NoMemoryError
      • ScriptError
        • LoadError
        • NotImplementedError
        • SyntaxError
      • SecurityError
      • SignalException
        • Interrupt
      • SystemExit
      • SystemStackError
      • StandardError
        • ArgumentError
        • FiberError
        • IOError
          • EOFError
        • IndexError
          • KeyError
          • StopIteration
        • LocalJumpError
        • NameError
          • NoMethodError
        • RangeError
          • FloatDomainError
        • RegexpError
        • RuntimeError
        • SystemCallError
        • ThreadError
        • TypeError
        • ZeroDivisionError

Definindo uma exception class:

classMyError < StandardError;end

Levantando uma exception:

classMyError < StandardError;endraiseMyErrorraiseMyError,'Exception'

Tratando exception com rescue:

classMyError < StandardError;endbegin# Minha implementação aqui.raiseMyErroriftruerescue=>ex# Aqui o tratamento da minha exception.puts"#{ex.class}: #{ex.message}"end# MyError: Mensagem

Tratando exception com rescue pelo tipo:

classMyError < ArgumentError;endbegin# Minha implementação aqui.raiseMyErroriftruerescueNoMethodError=>ex# Aqui o tratamento de método não definido.puts"NoMethodError: #{ex.class}: #{ex.message}"rescueArgumentError=>ex# Aqui o tratamento de erro nos argumentos.puts"ArgumentError: #{ex.class}: #{ex.message}"end# ArgumentError: MyError: Mensagem

Quando ocorre um exceção durante um tratamento, então é propagada uma nova exceção.

Usando o retry dentro de um tratamento de exceção:

tries=0begintries += 1xMethodrescueNoMethodError=>exputsex.messageretryiftries < 4end# Mensagem# Mensagem# Mensagem# Mensagem

A cláusula else geralmente é utilizada para um tratamento genérico onde outros tratamentos utilizando o rescue não forma efetivos:

beginraiseStandardErrorrescueNoMethodError=>exputs"NoMethodError: #{ex.message}"elseputs"GenericError"end# GenericError

A Cláusula ensure é utilizada como finalização do tratamento, ela é chama sempre após executar um rescue e até mesmo o else:

beginraiseNoMethodErrorrescueNoMethodError=>exputs"NoMethodError: #{ex.message}"ensureputs"E finalizou a exceção."end# NoMethodError: Mensagem# E finalizou a exceção.beginraiseStandardErrorrescueNoMethodError=>exputs"NoMethodError: #{ex.message}"elseputs"GenericError"ensureputs"E finalizou a exceção."end# GenericError# E finalizou a exceção.

Utilizando o rescue em um método, classe ou módulo.

classPatrick;endclassSpongeBob;endclassSquidward;endclassNotSpongeBobError < StandardError;endclassNotPatrickError < StandardError;enddefis_squarepants?(name)raiseNotSpongeBobErrorif !name.is_a?SpongeBobrescueraiseNotPatrickErrorif !name.is_a?Patrickelseputs"O nome da classe é:{Squidward.name}."ensureputs"Ele também é um personagem."endis_squarepants?(Squidward)# O nome da classe é: Squidward# Ele também é um personagem.

Utilizando o rescue como modificador:

putsis_squarepants?(Patrick)# NoMethodErrorputsis_squarepants?(SpongeBob)rescuetrue# true

Métodos, Procs e Lambdas:

Definindo métodos simples:

Definindo um método:

classSpongeBob;enddefis_squarepants?(name)name.is_a?(SpongeBob) ? true : falseend

Invocando um método:

classSpongeBob;enddefis_squarepants?(name)name.is_a?(SpongeBob) ? true : falseendis_squarepants?(SpongeBob.new)# true

Definindo um método Singleton:

bob='SpongeBob'defbob.is_squarepants?trueendbob.is_squarepants?# true

Indefinindo um método:

defis_squarepants?trueendis_squarepants?# true undef is_squarepants?is_squarepants?# NoMethodError

Nomes de Métodos:

Por convensão nomes de métodos começam sempre com letra minúscula, podem começar com letra maiúscula mas irão se parecer com uma constante. Quando o nome do método é maior que uma palavra, por convensão utiliza-se "_" para separa as palavras: "is_squarepants?". A convensão para métodos com ? no final, são métodos cujo valor retornado sempre será um boleano. A conversão para métodos com ! no final, são métodos cuja utilização deve ser com cautela, por exemplo, o método sort de um Array, ele copia o Array e ordena, já o método sort!, efetua o sort!` no mesmo array o redefinindo.

classSpongeBobdefis_squarepants?@squarepants || falseenddefis_squarepants!@squarepants=trueendendbob=SpongeBob.newputsbob.is_squarepants?# falsebob.is_squarepants!putsbob.is_squarepants?# true

Redefinindo os Métodos Operadores:

classSpongeBobdef +(value)"SpongeBob #{value}"endendputsSpongeBob.new + "SquarePants"# SpongeBob SquarePants

Definindo "alias" para os Métodos: (Não é possível fazer "Overloading" em um "alias")

defis_squarepants?trueendaliasis_sp?is_squarepants?putsis_squarepants?# trueputsis_sp?# true

Argumentos em Métodos:

Lista de Argumentos como Parâmetros:

defis_squarepants?(name, *args)puts"Name: #{name}"puts"Qualquer outro parâmetro informado: #{args}"endis_squarepants?('SpongeBob',true,'Patrick')# Name: SpongeBob# Qualquer outro parâmetro informado: [true, "Patrick"]

Hash como parâmetro:

defis_squarepants?(name='SpongeBob',options={squarepants: true})putsnameputsoptions[:squarepants]endputsis_squarepants?# SpongeBob# trueputsis_squarepants?('Patrick',squarepants: false)# Patrick# false

Bloco como parâmetro:

Se você prefere um controle explícito sobre o bloco, adicione um parâmetro final com um & na frente, então esse parâmetro irá referenciar o bloco, se for passado para o método, o tipo desse bloco sera um Proc ao invés de usar o yield você invocará através do método call.

defis_squarepants?(name, &block)block.call(name)endputsis_squarepants?('SpongeBob'){ |name| puts"#{name} SquarePants"}# SpongeBob SquarePantsputsis_squarepants?('Patrick'){ |name| puts"#{name} isn't SquarePants"}# Patrick isn't SquarePants

Se você prefere um controle mais específico ainda, defina um parâmetro como sendo o do bloco, o tipo deste parâmetro será um Proc e será invocado através do método call.

defis_squarepants?(name,block)block.call(name)endputsis_squarepants?('SpongeBob',proc{ |name| puts"#{name} SquarePants"})# SpongeBob SquarePantsputsis_squarepants?('Patrick',proc{ |name| puts"#{name} isn't SquarePants"})# Patrick isn't SquarePants

Procs e Lambdas:

Blocos são estruturas sintáticas em Ruby, não são objetos e não tem como os manipular como objetos. Então é possível criar um objeto representante de um bloco. Dependendo de como é criado o objeto, ele é chamado de proc ou lambda. Procs tem um comportamento como o de um bloco, e Lambdas tem um comportamento como um método. No entando os dois são instâncias da classe Proc.

Criando Procs:

p=Proc.new{ |adjective| "SpongeBob #{adjective}"}p.call('SquarePants')# SpongeBob SquarePantsp=proc{ |adjective| "SpongeBob #{adjective}"}p.call('SquarePants')# SpongeBob SquarePants

Criando Lambdas:

l=lambda{ |adjective| "SpongeBob #{adjective}"}l.call('SquarePants')# SpongeBob SquarePantsl=->(adjective){"SpongeBob #{adjective}"}l.call('SquarePants')# SpongeBob SquarePants

Descubrindo a quantidade de parâmetros obrigatórios de uma Proc:

p=proc{ |adjective| "SpongeBob is #{adjective}"}putsp.arity# 1l=->(adjective){"SpongeBob is #{adjective}"}l.arity# 1

Como diferenciar um lambda de um proc: O proc se parece como um bloco e tem um comportamento de bloco, o lambda é levemente modificado para parecer como um método. Para descobrir se o objeto é um lambda ou proc existe o método lambda? que retorna true se for um lambda e false se for um proc. O proc funciona como um bloco, seu retorno é propagado no contexto e não para o próprio proc. O lambda funciona como um método, seu retorno é propagado para o próprio lambda.

defis_squarepants?p=proc{puts'SpongeBob is SquarePants';return}p.callputs' and Patrick also'end# SpongeBob is SquarePantsdefis_squarepants?p=->{puts'SpongeBob is SquarePants';return}p.callputs" and Patrick isn't"end# SpongeBob is SquarePants and Patrick isn't 

Classes e Módulos:

Definindo uma classe simples:

Criando uma classe:

classSpongeBob;end

Instânciando a classe:

classSpongeBob;endsb=SpongeBob.newputssb.class# SpongeBobputssb.is_a?(SpongeBob)# true

Definindo o método inicializador de uma classe:

classSpongeBobdefinitialize(squarepants)@squarepants=squarepantsendend

Acessos e Atributos:

Provendo os acessos a uma váriavel de instância de forma manual:

classSpongeBobdefinitialize(squarepants)@squarepants=squarepantsenddefsquarepants;@squarepants;enddefsquarepants=(value)@squarepants=valueendendsb=SpongeBob.new(true)sb.squarepants=trueputssb.squarepants# true

Para prover esses acessos de formá automática o ruby fornece os métodos para serem definidos:

  • attr_reader - Cria o acesso de leitura
classSpongeBobattr_reader:squarepantsdefinitialize@squarepants=falseendendsb=SpongeBob.newputssb.squarepants# falsesb.squarepants=true# Erro
  • attr_writer - Cria o acesso de escrita
classSpongeBobattr_writer:squarepantsdefinitialize@squarepants=falseendendsb=SpongeBob.newsb.squarepants=trueputssb.squarepants# Erro
  • attr_accessor - Cria o acesso de leitura e escrita
classSpongeBobattr_accessor:squarepantsdefinitialize@squarepants=falseendendsb=SpongeBob.newsb.squarepants=trueputssb.squarepants# true

Definindo Operadores:

Em ruby você pode redefinir os operadores de uma classe:

  • Alguns operadores que podem ser definidos:
    • +
    • -
    • *
    • /
    • %
    • -@
    • +@
    • ~
    • !
    • =
    • ==
    • ===
classSpongeBobdefinitialize@he='SpongeBob'enddef +(value)"#{@he}#{value}"enddef ! "#{@he} isn't SquarePants"endendsb=SpongeBob.newputssb + 'SquarePants'# SpongeBob SquarePantsputs !sb# SpongeBob isn't SquarePants

Método de classe:

Métodos de Classe são métodos dos quais não dependem de uma instância ativa da classe.

classSpongeBobdefPoint.is_squarepants?(instance)instance.is_a?(SpongeBob)enddefself.is_squarepants?(instance)instance.is_a?(SpongeBob)endclass << selfdefis_squarepants?(instance)instance.is_a?(SpongeBob)endendendputsSpongeBob.is_squarepants?(SpongeBob.new)# true

Método de instância:

Método de Instância são os métodos dos quais dependem de uma instância ativa da classe.

classSpongeBobdefis_squarepants?(instance)instance.is_a?(SpongeBob)endendputsSpongeBob.new.is_squarepants?(SpongeBob.new)# true

Visibilidade de Métodos: Public, Protected, Private

  • Métodos de classe podem ser definidos públicos com este comando:
public_class_method:squarepants
  • Todos métodos normalmente são públicos, exceto o initialize que é sempre privado. Os métodos públicos podem ser invocados por qualquer um, não existe restrições.
classSpongeBobdefis_squarepants?self.is_a?SpongeBobendendsb=SpongeBob.newsb.is_squarepants?# true
  • Métodos de classe podem ser definidos privados com este comando:
private_class_method:squarepants
  • Os métodos privados, são métodos que só podem ser acessados internamente.
classKrustyKrabprivatedefis_employee?(instance)instance.is_a?(SpongeBob)end# Pode ser definido privado desta maneira também:# private :is_employee?endclassSpongeBob < KrustyKrabdefjobputsis_employee?(self)putsself.is_employee?(self)rescueputs'Não pode chamar o método privado por uma referência.'putsSpongeBob.new.is_employee?(SpongeBob.new)rescueputs'Não pode chamar o método privado externamente.'endendSpongeBob.new.job# true# Não pode chamar o método privado por uma referência.# Não pode chamar o método privado externamente.
  • Os métodos protegidos, são métodos iguais ao privados, só difere na medida em que pode ser explicitamente chamado em qualquer instância da classe.
classKrustyKrabprotecteddefis_employee?(instance)instance.is_a?(SpongeBob)end# Pode ser definido protegido desta maneira também:# protected :is_employee?endclassSpongeBob < KrustyKrabdefjobputsis_employee?(self)putsself.is_employee?(self)puts'Pode chamar o método protegido por uma referência.'putsSpongeBob.new.is_employee?(SpongeBob.new)puts'Pode chamar o método protegido externamente.'endendSpongeBob.new.job# true# Pode chamar o método protegido por uma referência# true# Pode chamar o método protegido externamente.

Heranças:

Herança não é muito diferente em ruby, quando você tem um classe SpongeBob que herda de Ocean dizemos que SpongeBob é uma subclass e Ocean é uma superclass. Uma classe pode ter infinitas subclasses mas apenas uma superclass. ruby não possui herança múltipla. Variáveis de instância, classe e constantes são herdadas e podem ser modificadas. O detalhes se for uma constante é que se estivermos criando alguma instância na superclass dela, a instância da subclass será diferente, pois sera criada uma nova.

  • Herança de métodos:
classOceandefhas_squarepants_here?trueendendclassSpongeBob < Ocean;endputsSpongeBob.new.has_squarepants_here?# true
  • Sobrescrevendo métodos:
classOceandefhas_squarepants_here?falseendendclassSpongeBob > Oceandefhas_squarepants_here?trueendendputsSpongeBob.new.has_squarepants_here?# true
  • Sobrescrevendo métodos privados e protegidos:
classOceanprivatedefhas_squarepants_here?falseendprotecteddefwhoiam?'Ocean'endendclassSpongeBob > Oceandefhas_squarepants_here?trueenddefwhoiam?'SpongeBob'endendputsSpongeBob.new.has_squarepants_here?# trueputsSpongeBob.new.whoiam?# SpongeBob
  • Algumas vezes necessitamos sobrescrever um método mas continuar com a implementação antiga, então usamos o super: (chaining)
classOceandefinitialize(whoiam='Ocean')@whoiam="I am #{whoiam}"endendclassSpongeBob < Oceanattr_accessor:presentationdefinitializesuper('SpongeBob')@presentation="#{@whoiam}, and I live in the ocean."endendputsSpongeBob.new.presentation# I am SpongeBob, and I live in the ocean.

Módulos:

Módulos são um coleção de módulos, constantes, classes e variáveis de classe. Um módulo não é instânciavel e não possui herança. Módulos usam namespaces e mixins, classes podem usar namespaces assim como os módulos, mas classes não usam mixins.

moduleOceandefself.spongebob_live_here?trueenddefself.patrick_live_here?trueendclassSpongeBobdefwhoiam?'SpongeBob'endendclassPatrickdefwhoiam?'Patrick'endendendputsOcean::SpongeBob.new.whoiam?# SpongeBobputsOcean.spongebob_live_here?# trueputsOcean::Patrick.new.whoiam?# PatrickputsOcean.patrick_live_here?# true

A diferença de mixins e herança é apenas que quando uma classe inclui um módulo ela não se torna filha deste módulo, apenas implementa os seus métodos. Os módulos e os mixins:

O include implementa os métodos do módulo como um método de instância na classe.

moduleOceandefself.whoiam?'Ocean'enddefi_live_in_ocean?trueendendclassSpongeBobincludeOceandefwhoiam?'SpongeBob'endendsb=SpongeBob.newputssb.whoiam?# SpongeBobputssb.i_live_in_ocean?# trueputsOcean.whoiam?# Ocean

O extend implementa os métodos do módulo como um método de classe na classe.

moduleOceandefself.whoiam?'Ocean'enddefi_live_in_ocean?trueendendclassSpongeBobextendOceandefwhoiam?'SpongeBob'endendsb=SpongeBob.newputssb.whoiam?# SpongeBobputsSpongeBob.i_live_in_ocean?# trueputsOcean.whoiam?# Ocean

Carregamento e Requerimento:

  • $LOAD_PATH ou $:

    • Variável global que contém um array com referência dos arquivos.
  • require

    • Faz a inclusão e a leitura do arquivo.
require'some_file'
  • require_relative
    • É utilizando quando existe a necessidade de referênciar um diretório/arquivo. Faz a leitura do arquivo.
require_relative'some_path/some_file'
  • load
    • Tem um comportamento semelhante ao require, a diferença é que necessita da extensão do arquivo, e pode ser executada diversas vezes.
load'some_path/some_file.rb'
  • autoload
    • Tem um comportamento semelhante ao require, porém só faz a leitura do arquivo quando acessado pela primeira vez.
autoload:SomeClass,'some_class'

Métodos Singleton em classe:

Todo objeto do Ruby está associado a duas classes: a classe que a instanciou e uma classe anônima, escondida, específica do objeto. Esta classe anônima é chamada de Singleton Class, mas antes de ter um nome oficial também era chamada de anonymous class, metaclass, eigenclass ou ghost class. A sintaxe mais comum para acessar a classe Singleton é:

classSpongeBobclass << selfdefwhoiam?'SpongeBob'endendendputsSpongeBob.whoiam?# SpongeBobputsSpongeBob.singleton_methods# [:whoiam?]

Toda vez que injeta métodos em um objeto, eles são adicionados como métodos singleton. O que é realmente importante saber é que estes métodos pertecem unicamente ao objeto em que foram definidos, não afetando nenhum outro objeto da hieraquia.

Testes:

Problema!

About

Ruby Presentation

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •