5. 10 COISAS SOBRE RUBY
#
1.
Tudo
eh
um
objeto
5.times
{
print
"Hello
World!"
}
#
2.
Blocos
sample_array.each
{
|element|
print
element
}
#
3.
Retorno
de
funcao
implicito
def
sum(a,b)
a
+
b
end
#
4.
Tudo
eh
aberto
class
Fixnum
def
previous
self
–
1
end
end
6.previous
#
5.
Operadores
unarios.
Nao
ha
++,
-‐-‐;
Use
+=
6. 10 COISAS SOBRE RUBY
#
6.
Atribuicao
paralela
a,
b
=
b,
a
#
7.
Cada
string
é
um
objeto
print
"hello".object_id
print
"hello".object_id
#
Um
novo
objeto
#
8.
Verdadeiro
e
falso
em
Ruby
if
0
print
"Hello
World"
end
#
9.
Suporte
a
faixa
de
numeros
e
expressoes
regulares
de
forma
nativa
(1..10).each
{
print
"Hello
World"
}
#
10.
Indicadores
de
metodo
class
Woman
def
loves?(thing)
thing
==
"chocolate"
?
true
:
false
end
end
7. APLICAÇÃO SIMPLES
puts
"Welcome!
What
do
you
want
to
be?"
#
Imprime
na
tela
choice
=
gets.strip
#
Lê
do
teclado
e
remove
n
if
choice
==
"Knight"
#
Comparacao
em
if
puts
"Then
a
princess
you
must
save"
elsif
choice
==
"Wizard"
#
Else
if
com
condicao
puts
"Then
a
book
you
must
find"
else
puts
"Just
stay
at
home"
end
puts
"What
is
your
strength?"
choice
=
gets.to_i
#
Le
do
teclado
e
converte
para
int
damage
=
choice.times.collect
do
rand(6)
+
1
end.inject(:+)
puts
"You
did
#{damage}
damage"
#
String
com
interpolacao
8. EXERCÍCIO
OBJETIVO
Criar o primeiro programa em Ruby: Calculadora de dano.
MÉTODO
§ Crie arquivo calculator.rb;
§ Leia do teclado a força e depois leia a armadura;
§ Para cada unidade de força jogue um dado de seis lados. A soma é o valor de ataque;
§ Para cada unidade de armadura jogue um dado de seis lados. A soma é o valor de defesa;
§ A subtração do ataque com a defesa é o dano total. Apresente este resultado;
§ Para executar o programa no terminal execute ruby calculator.rb
15 MIN
10. MVC
MODELS
- Representam os modelos do sistema
CONTROLLERS
- Representam as ações do sistema
VIEWS
- Interfaces resultantes de ações
ASSETS
- Arquivos auxiliares (images, js, css)
BIN
- Arquivo binários
LIB
- Módulos auxiliares
11. INICIALIZAÇÃO
#
bin/nome_da_aplicacao.rb
libs
=
[
File.expand_path('../../lib',
__FILE__),
File.expand_path('../../app',
__FILE__)
]
$LOAD_PATH.unshift
*Dir.glob(libs)
require
"nome_da_aplicacao"
#
lib/nome_da_aplicacao.rb
#
inicialmente
vazio
$
ruby
bin/nome_da_aplicacao.rb
Para executar faça uso do seguinte comando no terminal:
12. EXERCÍCIO
OBJETIVO
Construir a sua arquitetura
MÉTODO
§ A partir dos conceitos dados monte a sua arquitetura MVC;
§ Crie o arquivo de inicialização da aplicação;
§ Crie o arquivo de gerenciamento de dependências;
§ Para testar coloque um comando para escrita na tela no arquivo de dependências;
§ Execute;
§ Se funciona, apague a linha usada o comando de escrita na tela;
5 MIN
17. MÓDULOS EM RUBY
#
lib/save_the_princess/die.rb
class
Die
@@sides
=
6
#
Roll
the
die
#
You
can
change
the
amount
of
sides.
Default
is
6.
def
self.roll(sides
=
@@sides)
rand(6)
+
1
end
end
#
lib/save_the_princess.rb
require
"save_the_princess/die.rb"
Adicionar classe à lista de dependências
18. INTERACTIVE RUBY
$
irb
-‐Ibin
-‐rsave_the_princess
>
Die.roll
=>
4
Ambiente interativo para desenvolvimento e teste de comandos em Ruby
19. CLASSES EM RUBY
#
app/models/character.rb
class
Character
#
Character
profile
attributes
attr_accessor
:name
attr_accessor
:strength,
:skill,
:resistance,
:armor,
:fire_power
#
The
sum
of
the
amount
of
strength
die
rolls.
def
attack
strength.times.collect
do
Die.roll
end.inject(:+)
end
#
The
sum
of
the
amount
of
armor
die
rolls.
def
defend
armor.times.collect
do
Die.roll
end.inject(:+)
end
end
LEMBRE-SE DE ADICIONAR A DEPENDÊNCIA!
21. EXERCÍCIO
OBJETIVO
Escrever as classes Die e Character;
MÉTODO
§ Na classe Die deve existir o método self.roll representando um jogar de dados;
§ Na classe Character defina os seus atributos e os métodos attack e defend;
§ Execute no IRB;
§ Em Character adicione um método para calcular a vida do personagem:
§ O método calculate_health_points é baseado na resistência do usuário;
§ É necessário guardar a vida em um atributo chamado max_health_points;
30 MIN
22. CONSTRUTORES
class
Character
...
attr_accessor
:max_health_points
#
Character
constructor.
Sets
the
attributes
default
values.
def
initialize(params
=
{})
@name
=
params[:name]
||
""
@strength
=
params[:strength]
||
0
@skill
=
params[:skill]
||
0
@resistance
=
params[:resistance]
||
0
@armor
=
params[:armor]
||
0
@fire_power
=
params[:fire_power]
||
0
calculate_max_health_points
end
end
self.name
=
@name
=
...
25. HERANÇA
class
Knight
<
Character
#
Do
an
attack
with
a
bonus
of
3
def
slash
attack
+
3
end
end
$
irb
-‐Ibin
-‐rsave_the_princess
>
k
=
Knight.new
name:
"Marc",
strength:
2,
skill:
4,
resistance:
2
=>
#<Knight:0x007ffcf280e750
@name="Marc",
@strength=2,
@skill=4,
@resistance=2,
@armor=0,
@fire_power=0,
@max_health_points=8>
>
k.slash
=>
9
>
c
=
Character.new
name:
"James",
strength:
3,
skill:
2,
resistance:
1
=>
#<Character:0x007f93a30f90e0
@name="James",
@strength=3,
@skill=2,
@resistance=1,
@armor=0,
@fire_power=0,
@max_health_points=3>
>
c.slash
NoMethodError:
undefined
method
`slash'
for
#<Character:0x007f93a30f90e0>
26. EXERCÍCIO
OBJETIVO
Escrever a classe Dungeon e as classes filhas de Character;
MÉTODO
§ Com o que já aprendeu construa a classe Dungeon, com seu nome e tipo;
§ Combine com o colega ao lado quais classes filhas cada um vai escrever;
§ Escreva as classes e partilhe com o seu colega;
§ No arquivo de inicialização carregue um array de personagens e masmorras para disponibilizar
para a aplicação, sem ter a necessidade de criar toda vez que é inicializada.
50 MIN
#
bin/save_the_princess.rb
@characters
=
[Character.new
...,
...]
27. MODIFICADORES DE ACESSO
class
Character
...
attr_reader
:max_health_points
private
#
Calculate
max
health
based
on
resistance.
def
calculate_max_health_points
...
end
end
>
c
=
Character.new
name:
"James",
strength:
3,
skill:
2,
resistance:
1
=>
#<Character>
>
c.max_health_points
=
1000
NoMethodError:
undefined
method
`max_health_points='
for
#<Character>
>
c.calculate_max_health_points
NoMethodError:
private
method
`calculate_max_health_points'
called
for
#<Character>
>
c.max_health_points
5
31. Battle
...
start()
ALTA COESÃO E BAIXO ACOPLAMENTO
Round
...
start()
Turn
...
start()
Importante! Ruby não possui interfaces. É necessário implementar uma solução.
OBJETIVO
Classe deve fazer o que propõe
Classe deve possuir o mínimo de relacionamento possível
32. A BATALHA
REGRAS
1. Iniciativa: Joga-se um dado. Aquele que obtiver maior valor ataca primeiro. Caso igual joga-se de novo;
2. Ataque: Caso seja um ataque normal, seguir para 3, senão fazer um teste de habilidade;
3. Dano: A soma resultante de lances de dados equivalente à força ou poder de fogo;
4. Defesa: A soma resultante de lances de dados equivalente à defesa. Valor do dano é subtraído;
5. Pontos de vida: O dano que ultrapassa a soma da Armadura é subtraído de seus pontos de vida;
6. Retaliação: Se ainda estiver vivo, o lutador que foi atacado revida e os passos 2 a 4 são repetidos;
33. CLASSES DE COMBATE
#
app/models/battle.rb
class
Battle
attr_accessor
:challenger,
:opponent
#
Armazena
os
combatentes
def
initialize(params
=
{})
end
#
Instancia
rodadas
até
que
#
os
pontos
de
vida
de
um
#
pesonagem
chegue
a
zero.
#
Recupera
os
combatentes.
def
start
end
end
#
app/models/battle.rb
class
Battle::Round
attr_accessor
:challenger,
:opponent
#
Armazena
os
combatentes
def
initialize(params
=
{})
end
#
Verifica
quem
terá
a
#
iniciativa
e
istancia
#
turnos.
def
start
end
end
#
app/models/battle.rb
class
Battle::Round::Turn
attr_accessor
:attacker,
:defender
#
Armazena
os
combatentes
def
initialize(params
=
{})
end
#
Calcula
o
dano
feito
em
#
combate.
def
start
end
end
34. EXERCÍCIO
OBJETIVO
Escrever a classe Battle e todas as suas dependências;
MÉTODO
§ Desenvolva as classes Turn, Round e Battle nesta ordem;
30 MIN
35. EXERCÍCIO
OBJETIVO
Adicionar class Team. Uma dungeon pode ter vários times;
MÉTODO
§ Desenvolver uma classe Team que tem um nome e um vetor de Characters;
§ Adicione ao método initialize da Dungeon para receber times de oponentes como parâmetro;
§ Crie um método visit para Team que receba uma Dungeon como parâmetro;
§ Nesse método os oponentes presentes naquela dungeon devem ser enfrentados;
§ O vencedor será a batalha entre o primeiro do time 1 luta contra o primeiro do time 2;
2 HORAS
37. DON’T REPEAT YOURSELF (DRY)
#
app/models/character.rb
class
Character
...
#
The
sum
of
the
amount
of
strength
die
rolls.
def
attack
[strength,
fire_power].max.times.collect
do
Die.roll
end.inject(:+)
end
#
The
sum
of
the
amount
of
armor
die
rolls.
def
defend
armor.times.collect
do
Die.roll
end.inject(:+)
end
end
38. DON’T REPEAT YOURSELF (DRY)
#
app/models/character.rb
class
Character
...
#
The
sum
of
the
amount
of
strength
die
rolls.
def
attack
roll_die_for
[strength,
fire_power].max
end
#
The
sum
of
the
amount
of
armor
die
rolls.
def
defend
roll_die_for
armor
end
protected
def
roll_die_for(attribute)
attribute.times.map{
Die.roll
}.inject(:+)
end
end
41. EXERCÍCIO
OBJETIVO
Refatorar a classe Battle e seus sub-módulos;
MÉTODO
§ Simplificar as funções das classes criando classes mais específicas;
§ Garantir que a classe funciona da mesma forma;
§ Gere a documentação do seu projeto com RDoc;
1 HORA
42. EXERCÍCIO
OBJETIVO
Classe Battle deve prover batalhas entre times;
MÉTODO
§ Alterar a classe Battle para receber dois times (ao invés de characters);
§ Para cada personagem no time desafiante (challenger) deve ser feita uma rodada escolhendo um
inimigo aleatório, assim como, o time desafiado (opponent) deve ter uma rodada para cada
integrante escolhendo um adversário aleatório;
§ Tente fazer o mínimo de alterações nas classes Turn e Round;
4 HORAS
#
Dica
@challengers.each
do
|challenger|
Round.new
challenger:
challenger,
opponent:
@opponents.shuffle[0]
end