ruby
DESCRIPTION
O que Ruby está trazendo ao mundo de desenvolvimento de software.TRANSCRIPT
![Page 1: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/1.jpg)
Ecossistema Ruby
O que Ruby está trazendo ao mundo de desenvolvimento de software.
@rafaeldx7
![Page 2: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/2.jpg)
@rafaeldx7Rafael Almeida de Carvalho
![Page 3: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/3.jpg)
RubyÉ uma linguagem de programação.
![Page 4: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/4.jpg)
Interpretada
Multiparadigma
Tipagem Dinâmica
Tipagem Forte
Código Aberto
![Page 5: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/5.jpg)
Criada por Yukihiro "Matz" Matsumoto
“I wanted a scripting language that was more powerful than Perl, and more object-oriented than Python.”
http://linuxdevcenter.com/pub/a/linux/2001/11/29/ruby.html
![Page 6: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/6.jpg)
Início do desenvolvimentoDez/1993
Dez/1994 Primeira versão alpha
Dez/1995 Release 0.95
Dez/1996 Versão 1.0
Ago/2010 Versão 1.9.2
![Page 7: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/7.jpg)
Interpretadores
![Page 8: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/8.jpg)
MRIMatz Ruby Interpreter
![Page 9: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/9.jpg)
![Page 10: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/10.jpg)
for .NET 4.0, Silverlight 4 and Windows Phone 7.
![Page 11: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/11.jpg)
![Page 12: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/12.jpg)
blá blá blá...
CADÊ O CÓDIGO!?
![Page 13: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/13.jpg)
Imprimir os númerosímpares entre
1 e limit.
![Page 14: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/14.jpg)
def impares(limit)1.upto(limit).select { |n| n.odd? }
end
![Page 15: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/15.jpg)
Tipagem Dinâmica
![Page 16: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/16.jpg)
nome = "Rafael"# => "Rafael"
nome.class# => String
nome = :rafael# => :rafael
nome.class# => Symbol
![Page 17: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/17.jpg)
Tipagem Forte!
![Page 18: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/18.jpg)
ruby $> 1 + "1"
![Page 19: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/19.jpg)
TypeError: String can't be coerced into Fixnum! from (irb):21:in `+'! from (irb):21
ruby $> 1 + "1"
![Page 20: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/20.jpg)
TUDO é um objeto!
![Page 21: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/21.jpg)
3.times { puts "Hi!" }
# Hi!# Hi!# Hi!
![Page 22: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/22.jpg)
"Ruby eh show!".split.reverse
![Page 23: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/23.jpg)
"Ruby eh show!".split.reverse
=> ["show!", "eh", "Ruby"]
![Page 24: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/24.jpg)
true.class => TrueClass
true.methods.count => 48
true.to_s => “true”
![Page 25: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/25.jpg)
nil.class => NilClass
0.10.class => Float
![Page 26: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/26.jpg)
Métodos são objetos!
![Page 27: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/27.jpg)
42.next# => 43
method = 42.method :next# => #<Method: Fixnum(Integer)#next>
method.call# => 43
method.class# => Method
![Page 28: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/28.jpg)
Operadores são Métodos
![Page 29: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/29.jpg)
2 + 2# => 4
2.+(2)# => 4
2.public_methods.sort# => ["!", "!=", "!~", "%", "&", "*","**", "+", "+@", "-", "-@", "/", "<","<<","<=", "<=>", "==", "===", "=~",">", ">=", ">>", "[]", "^", ... ]
![Page 30: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/30.jpg)
class Fixnum def +(value) "#{self} + #{value}" end def ==(value) self * value endend
puts 4 + 4# => "4 + 4"
puts 3 == 2# => 6
![Page 31: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/31.jpg)
Executar um método é enviar uma mensagem
ao objeto.
![Page 32: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/32.jpg)
2 + 2#=> 4
2.send('+', 2)=> 4
['rafael', 'dx7'].join=> "rafaeldx7"
['rafael', 'dx7'].send(:join)=> "rafaeldx7"
![Page 33: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/33.jpg)
MétodosSEMPRE retornam valor!
![Page 34: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/34.jpg)
def um_metodoend
um_metodo# nil
def um_metodo1 == 2 - 1
end
um_metodo# true
def um_metodo "Opa!"end
um_metodo# "Opa!"def um_metodo (1..5).to_aend
um_metodo#[1,2,3,4,5]
![Page 35: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/35.jpg)
def um_metodoreturn 1, 2, 3
end
a, b, c = um_metodo
puts a, b, c=> #1=> #2=> #3
![Page 36: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/36.jpg)
Metaprogramação
![Page 37: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/37.jpg)
class Fooend
Foo.class_eval dodefine_method("novo") do |arg|puts arg
endend
f = Foo.newf.novo("123") => # 123
![Page 38: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/38.jpg)
class Foodef method_missing(name)puts "método #{name} desconhecido"
endend
f = Foo.new f.xpto => método xpto desconhecido
![Page 39: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/39.jpg)
Mais JRuby
![Page 40: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/40.jpg)
fizzbuzz
![Page 41: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/41.jpg)
def fizzbuzz(number) resp = "" resp.tap do resp << "fizz" if number.modulo(3) == 0 resp << "buzz" if number.modulo(5) == 0 resp << number.to_s if resp.empty? endend
![Page 42: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/42.jpg)
def fizzbuzz(number) resp = "" resp.tap do resp << "fizz" if number.modulo(3) == 0 resp << "buzz" if number.modulo(5) == 0 resp << number.to_s if resp.empty? endend
pane = javax.swing.JOptionPane
numbers = pane.show_input_dialog("Quantos números?").to_i
![Page 43: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/43.jpg)
def fizzbuzz(number) resp = "" resp.tap do resp << "fizz" if number.modulo(3) == 0 resp << "buzz" if number.modulo(5) == 0 resp << number.to_s if resp.empty? endend
pane = javax.swing.JOptionPanelist = java.util.ArrayList.new
numbers = pane.show_input_dialog("Quantos números?").to_i
numbers.times do |i| list << fizzbuzz(i + 1)end
![Page 44: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/44.jpg)
def fizzbuzz(number) resp = "" resp.tap do resp << "fizz" if number.modulo(3) == 0 resp << "buzz" if number.modulo(5) == 0 resp << number.to_s if resp.empty? endend
pane = javax.swing.JOptionPanelist = java.util.ArrayList.new
numbers = pane.show_input_dialog("Quantos números?").to_i
numbers.times do |i| list << fizzbuzz(i + 1)end
pane.show_message_dialog(nil, list.to_s)
![Page 45: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/45.jpg)
require 'java'
def fizzbuzz(number) resp = "" resp.tap do resp << "fizz" if number.modulo(3) == 0 resp << "buzz" if number.modulo(5) == 0 resp << number.to_s if resp.empty? endend
pane = javax.swing.JOptionPanelist = java.util.ArrayList.new
numbers = pane.show_input_dialog("Quantos números?").to_i
numbers.times do |i| list << fizzbuzz(i + 1)end
pane.show_message_dialog(nil, list.to_s)
![Page 46: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/46.jpg)
$ ruby fizzbuzz.rb
![Page 47: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/47.jpg)
$ ruby fizzbuzz.rb
![Page 48: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/48.jpg)
$ ruby fizzbuzz.rb
![Page 49: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/49.jpg)
DSLDomain Specific Language
![Page 50: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/50.jpg)
describe Account do context "transfering money" do it "deposits transfer amount to the other account" do source = Account.new(50, :USD) target = mock('target account') target.should_receive(:deposit).with(Money.new(5, :USD)) source.transfer(5, :USD).to(target) end
it "reduces its balance by the transfer amount" do source = Account.new(50, :USD) target = stub('target account') source.transfer(5, :USD).to(target) source.balance.should == Money.new(45, :USD) end endend
RSpec - Testando código Ruby
![Page 51: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/51.jpg)
# language: pt
Funcionalidade: Usuário gerenciando produtos Como um usuário com permissão de gerenciar produtos Com o objetivo de dividir responsabilidades E custos por produto Eu deveria poder cadastrar E gerenciar uma lista de produtos
Cenário: Listar produtos Dado que eu esteja logado E que existem os produtos produto 1, produto 2 E que eu esteja na página inicial Quando eu clico "Produtos" Então eu devo ver "produto 1" E eu devo ver "produto 2"
Cucumber - Testes de Aceitação
![Page 52: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/52.jpg)
RubyGems
![Page 53: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/53.jpg)
$ gem install ruby-bitlySuccessfully installed mime-types-1.16Successfully installed rest-client-1.6.0Successfully installed json_pure-1.4.3Successfully installed ruby-bitly-0.1.34 gems installed
$ gem list
*** LOCAL GEMS ***
json_pure (1.4.3)mime-types (1.16)rest-client (1.6.0)ruby-bitly (0.1.3)
Instalando uma gem
![Page 54: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/54.jpg)
$ bitly http://rafaeldx7.github.comShort url: http://bit.ly/aRr9aH
Usando a gem em linha de comando
![Page 55: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/55.jpg)
require 'rubygems'require 'ruby-bitly'
bitly = Bitly.shorten 'http://rafaeldx7.github.com', 'rafaeldx7', 'R_xxxxxxxxxxxxxxxxxxxxxxxxxxx'
puts bitly.url
=> "http://bit.ly/aRr9aH"
Usando a gem em um código Ruby
![Page 56: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/56.jpg)
![Page 57: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/57.jpg)
![Page 58: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/58.jpg)
Um framework Web para Ruby
Extraído de uma aplicação real
Criado em julho/2004
É um conjunto de gems
Uma DSL para aplicações web
![Page 59: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/59.jpg)
Instalação do Rails$ gem install railsSuccessfully installed activesupport-3.0.1Successfully installed builder-2.1.2Successfully installed i18n-0.4.2Successfully installed activemodel-3.0.1Successfully installed rack-1.2.1Successfully installed rack-test-0.5.6Successfully installed rack-mount-0.6.13Successfully installed tzinfo-0.3.23Successfully installed abstract-1.0.0Successfully installed erubis-2.6.6Successfully installed actionpack-3.0.1Successfully installed arel-1.0.1Successfully installed activerecord-3.0.1Successfully installed activeresource-3.0.1Successfully installed polyglot-0.3.1Successfully installed treetop-1.4.8Successfully installed mail-2.2.9Successfully installed actionmailer-3.0.1Successfully installed thor-0.14.4Successfully installed railties-3.0.1Successfully installed rails-3.0.121 gems installed
![Page 60: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/60.jpg)
Criando uma aplicação Rails
$ rails new sc2010 create create README create Rakefile create config.ru create .gitignore create Gemfile create app create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/mailers create app/models
.
.
.$ bundle install
![Page 61: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/61.jpg)
$ rails server
![Page 62: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/62.jpg)
![Page 63: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/63.jpg)
Vamos fazer alguma coisa...$ rails generate scaffold task name:string done:boolean invoke active_record create db/migrate/20101111152244_create_tasks.rb create app/models/task.rb invoke test_unit create test/unit/task_test.rb create test/fixtures/tasks.yml route resources :tasks invoke scaffold_controller create app/controllers/tasks_controller.rb invoke erb create app/views/tasks create app/views/tasks/index.html.erb create app/views/tasks/edit.html.erb create app/views/tasks/show.html.erb create app/views/tasks/new.html.erb create app/views/tasks/_form.html.erb invoke test_unit create test/functional/tasks_controller_test.rb invoke helper create app/helpers/tasks_helper.rb invoke test_unit create test/unit/helpers/tasks_helper_test.rb invoke stylesheets create public/stylesheets/scaffold.css
![Page 64: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/64.jpg)
Criando o DB e iniciando o servidor
$ rake db:migrate(in /Users/rafael/Sites/playground/sc2010)== CreateTasks: migrating ==============================================-- create_table(:tasks) -> 0.0026s== CreateTasks: migrated (0.0034s) =====================================
$ rails server=> Booting WEBrick=> Rails 3.0.1 application starting in development on http://0.0.0.0:3000=> Call with -d to detach=> Ctrl-C to shutdown server[2010-11-11 13:25:52] INFO WEBrick 1.3.1[2010-11-11 13:25:52] INFO ruby 1.8.7 (2010-08-16) [x86_64-darwin10.4.0][2010-11-11 13:25:52] INFO WEBrick::HTTPServer#start: pid=7367 port=3000
![Page 65: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/65.jpg)
![Page 66: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/66.jpg)
![Page 67: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/67.jpg)
![Page 68: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/68.jpg)
![Page 69: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/69.jpg)
![Page 70: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/70.jpg)
![Page 71: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/71.jpg)
Uma tarefa precisa ter um nome
class Task < ActiveRecord::Base validates_presence_of :nameend
![Page 72: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/72.jpg)
![Page 73: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/73.jpg)
class Task < ActiveRecord::Base validates_presence_of :name belongs_to :user has_many :statusesend
![Page 74: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/74.jpg)
Quem usa Rails?
![Page 75: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/75.jpg)
![Page 76: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/76.jpg)
![Page 77: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/77.jpg)
![Page 78: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/78.jpg)
![Page 79: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/79.jpg)
![Page 80: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/80.jpg)
![Page 81: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/81.jpg)
![Page 82: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/82.jpg)
![Page 83: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/83.jpg)
![Page 84: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/84.jpg)
![Page 85: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/85.jpg)
![Page 86: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/86.jpg)
![Page 87: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/87.jpg)
![Page 88: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/88.jpg)
![Page 89: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/89.jpg)
Como aprender?
![Page 90: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/90.jpg)
![Page 91: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/91.jpg)
![Page 92: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/92.jpg)
![Page 94: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/94.jpg)
aprendaaprogramar.rubyonrails.pro.br
![Page 95: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/95.jpg)
![Page 96: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/96.jpg)
![Page 97: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/97.jpg)
![Page 98: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/98.jpg)
![Page 99: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/99.jpg)
Foi divertido? =D
![Page 100: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/100.jpg)
Perguntas?
![Page 101: Ruby](https://reader033.vdocuments.site/reader033/viewer/2022052823/55530442b4c9054e3f8b4863/html5/thumbnails/101.jpg)
Obrigado!@rafaeldx7