Ruby on Rails do Básico ao Avançado Aula 01 Introdução ao Ruby, Instalação e Linguagem 1 Curso online de Ruby On Rails Se você se inscreveu neste curso, obviamente está interessado em aprender ou avançar seu conhecimento sobre Rails e a linguagem sobre qual o mesmo foi criado. O nosso objetivo é ajudar você a alcançar este objetivo. Ruby on Rails: Do Básico ao Avançado é um curso voltado tanto para programadores que não possuem qualquer conhecimento de Rails, quanto para aqueles programadores que já utilizam o Rails de alguma forma e querem avançar o seu conhecimento em áreas nas quais talvez não estejam aproveitando bastante o que o framework oferece. O material que você começa a ler agora é inteiramente novo e preparado especificamente para o curso. Tendo se matriculado no curso, você já sabe que o mesmo é composto de aulas com material para estudo próprio que incluem tanto partes teóricas como partes práticas, e aulas online, onde estaremos interagindo para esclarecer dúvidas, explicar partes mais espinhosas do Ruby e do Rails, e, de uma maneira geral, expandir sobre o que foi introduzido na aula de estudo próprio anterior. Esperamos que você não só aprenda como também se divirta bastante. Tanto o Ruby quanto o Rails foram inventados por seus criadores não só para facilitar suas vidas, mas também para retornar aos programadores o conceito de que a programação, mesmo sendo o seu trabalho diário, pode ser divertida. Sendo assim, abra o seu editor, escreva algum código e tenha um bom tempo conosco! História Um curso de Ruby on Rails não poderia começar em outro lugar que não seja a própria linguagem no qual o mesmo foi escrito. Sendo assim, começamos pelo Ruby. De uma linguagem basicamente desconhecida em 2004 a uma das linguagens mais utilizadas atualmente, o Ruby percorreu um rápido e espetacular caminho. Criada por Yukihiro “Matz” Matsumoto em 1993, a linguagem cresceu rapidamente no Japão, terra de seu inventor, mas nunca chegou a ter reconhecimento internacional até que um framework novo, chamado Rails, conquistasse o mundo do desenvolvimento Web em meados de 2003. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 2 Curso online de Ruby On Rails Chamado simplesmente de Ruby on Rails, esse novo framework fazia um uso inovador do Ruby e de suas características de meta-programação para encaixar as peças do desenvolvimento Web em um todo coerente que poucas vezes surgira no mercado. Desnecessário dizer, o Rails se tornou um sucesso instantâneo trazendo o Ruby para a frente das câmeras e mostrando que existiam outras linguagens, além das tradicionais, que podiam oferecer muito ao programador interessado. No Japão, o Ruby já era, inclusive, mais popular do que o Python. Sua brilhante aplicação no Rails lhe deu um reconhecimento maior e o tornou a ferramenta de escolha de milhões de programadores, não só para desenvolvimento Web como basicamente para qualquer tarefa que exija uma linguagem dinâmica e produtiva. O sucesso atual do Ruby se deve, sem dúvida ao Rails. Sem o Rails, é provável que o Ruby tivesse surgido eventualmente no cenário central das linguagens de programação, mas sem todo o hype e visibilidade que o mesmo possui atualmente. O que teria sido uma pena já que o Ruby, como mencionado acima, é uma ferramenta fantástica não só para desenvolvimento Web mas também para a miríade de tarefas que um programador precisa executar do seu dia-a-dia. Um dos motivos da criação do Ruby, segundo o seu inventor, foi o foco no programador e na necessidade de maior produtividade com menor stress. De acordo com Matz, as linguagens de programação são focadas em extrair o máximo de performance da máquina na qual estão rodando, enquanto o Ruby privilegia o máximo de performance para o programador. Tudo isso dito, não se pode extrair a conclusão de que o Ruby seja a linguagem perfeita. Como qualquer linguagem, o Ruby tem suas vantagens e desvantagens e deve ser usada apropriadamente. Ainda assim, como esperamos mostrar durante o curso, escolher o Ruby como uma linguagem a mais para o seu currículo é algo que pode beneficiar qualquer programador. Características Até o momento não falamos das características do Ruby. Para isso, vamos usar as palavras do seu próprio criador. Em uma tradução livre, ele diz o seguinte: Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 3 Curso online de Ruby On Rails “O Ruby é uma linguagem de scripting interpretada cujo objetivo é tornar a programação orientada a objetos simples e rápida. Como Perl, ela possui muitas características de processamento de textos e acesso ao sistema. É simples, direta, extensível e portável.”1 Quebrando isso em partes, o Ruby é antes de tudo uma linguagem de propósito geral voltada para scripting, ou seja, para a realização daquelas tarefas rápidas que tomariam um tempo enorme em outras linguagens não específicas como C ou Pascal. Apesar disso, o Ruby é completamente orientado a objetos, o que o torna extremamente poderoso e facilita a vida do programador em muitos sentidos. É uma linguagem prática, como Perl, que possui características inerentes para processamento de texto e acesso as vários objetos do sistema operacional de modo a ajudar o programador em todos os aspectos do seu uso diário. Finalmente, possui uma sintaxe simples e extensível que ajuda programadores iniciantes e capacita programadores experientes a extrair o máximo da mesma. Ruby herdou quase todas suas características de duas linguagens díspares: Perl e Smalltalk. Como Perl, Ruby possui as características práticas mencionadas acima, e, como Smalltalk, Ruby possui características de programação orientada a objetos e meta-programação que a levam a um nível superior a muitas linguagens aparentemente equivalentes como PHP. Além de Perl e Smalltalk, Ruby também tem um quê de Eiffel e Ada em sua sintaxe, gerando código legível e de fácil manutenção. Usando ainda o mesmo texto do qual a citação anterior foi extraída, Matz diz o seguinte sobre as características do Ruby: − Possui sintaxe simples, inspirada em Eiffel e Ada; − Possui recursos para a captura de exceções, como Java e Python, que tornam o tratamento de erros simples e direto; − Tudo na linguagem é um objeto. Isso significa que todo e qualquer dado representado na linguagem é um objeto, como em Smalltalk. Não há exceções. De tipos primitivos a objetos a classes, a representação é coerente. 1 http://www2.ruby-lang.org/en/20020101.html Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 4 Curso online de Ruby On Rails − Sendo completamente orientada a objetos, Ruby não possui funções ou procedimentos. Todos objetos possuem métodos (ou mensagens) que recebem determinados parâmetros e causas mudanças de estado nesses objetos. Mesmo os operadores como + e / são simplesmente métodos disfarçados sintaticamente. − Todas as classes e objetos são abertos. Isso significa que mesmo as classes básicas como String (que representa informação textual) e Fixnum (que representa números inteiros) podem ser alteradas pelo programador. Significa também que instâncias de uma classe podem ser modificadas para se comportar diferentemente de outras instâncias. Finalmente, significa que qualquer coisa pode ser redefinida. É possível, por exemplo, redefinir operações matemáticas e criação de instâncias. − Ruby possui herança simples. Objetos são estendidos via módulos conhecidos como mixins que são coleções de métodos. Isso significa que os métodos de uma classe são apenas mensagens e que objetos diferentes podem responder às mesmas mensagens facilitando o uso por parte do programador. − Ruby possui closures 2 reais. Closures são funções que carregam consigo o contexto no qual foram criadas. Isso permite programação e metaprogramação em um nível muito acima da maioria das linguagens imperativas comuns. Significa também que você pode passar funções como parâmetros, aumentando a capacidade da linguagem da forma que for necessária. − Ruby possui blocos de execução de código que podem ser passados para métodos como parâmetros ou convertidos em closures. − Ruby possui um garbage collector3 eficiente. Isso significa que programadores não precisam se preocupar com gerenciamento de memória de uma maneira geral. − Ruby pode ser estendido via C ou qualquer outra linguagem compilada se necessário. 2 http://en.wikipedia.org/wiki/Closure_%28computer_science%29 3 http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29 Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 5 Curso online de Ruby On Rails − Variáveis em Ruby não precisam ser declaradas e são dinâmicas como o resto da linguagem. − Ruby roda em basicamente qualquer sistema operacional de amplo uso atualmente, incluindo qualquer Linux, Windows, e Mac OS X. Existem outras características notáveis, mas essas já dão um bom exemplo do que torna o Ruby uma linguagem interessante. Todas as características acima serão exploradas ao longo do curso, de modo que você poderá se familiarizar com as mesmas e extrair o máximo do que o Ruby oferece. Vantagens e Desvantagens As características acima mostram que o Ruby possui bastante vantagens sobre linguagens de longo uso do mercado. Por exemplo, ao contrário de usuários de C ou Pascal, usuários de Ruby não precisam se preocupar em alocar memória—o Ruby toma conta dessa necessidade e, com raras exceções, o programador pode se esquecer de que memória real está sendo alocada, usada e descartada na execução de seus programas. Sendo completamente orientado a objetos, o Ruby fornece uma interface comum para o programador que nunca o confunde. Todos objetos se comportam da mesma maneira, todos objetos respondem a mensagens e mesmo o “açúcar sintático” é coerentemente empregado ao longo da implementação do Ruby. O Ruby é dinâmico e reflexivo. O primeiro atributo significa que não há restrições na linguagem sobre o tipo e a movimentação de dados ao longo da execução de um programa. O segundo significa que é possível explorar todas as características de um objeto, independentemente do mesmo ter sido criado internamente pelo Ruby ou externamente pelo programador. Todas essas vantagens não significam que o Ruby seja destituído de desvantagens. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 6 Curso online de Ruby On Rails Para citar duas delas, o Ruby possui sua própria implementação interna de threading4 . Embora isso a torne portável a todas plataformas onde o Ruby está, significa também o Ruby não consegue aproveitar tão bem sistemas multi-processados sem esforço por parte do programador e que certas condições de travamento e concorrência são mais difíceis de serem prevenidas. É importante recordar que esta limitação ocorre somente quando se utiliza o interpretador padrão do Ruby (que estaremos utilizando no curso e que é o mais utilizado atualmente). Existem diversos projetos, que serão discutidos mais tarde, que trabalham para melhorar esta implementação interna de threading, como o JRuby (do qual o Ruby utiliza a máquina virtual do Java para ser executado), IronRuby (utilizando o framework .Net como base) e o MagLev (do qual utiliza a máquina virtual GemStone de Smalltalk). Uma outra desvantagem está no fato de que existem certas construções da linguagem, como a sobrecarga de operadores, que são limitadas pela implementação em C do Ruby, impedindo que algumas características avançadas da linguagem sejam exploradas. Essas duas e as outras desvantagens do Ruby (como, por exemplo, o fato de que hoje sua máquina virtual é mais lenta que as equivalentes de Python e Perl) não devem ser um motivo de impedimento para o uso da linguagem. Primeiro porque poucas vezes elas impactam o desenvolvimento e, quando impactam, soluções alternativas existem para uso no Ruby ou em conjunção com outras linguagens. Segundo, porque – como já foi explicado sobre as threads – as mesmas já estão sendo resolvidas em novas implementações do Ruby como JRuby, IronRuby, MagLev e Ruby 1.9 (que já foi lançado em 2009 e pronta para produção). Agora que conhecemos mais do Ruby, podemos passar para o aspecto prático que é a instalação do mesmo. Aqui começa a nossa aventura. Mais uma vez, divirta-se! 4 http://en.wikipedia.org/wiki/Green_threads Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 7 Curso online de Ruby On Rails Instalação Vamos caminhar passo a passo sobre as formas de instalar o interpretador do Ruby nas principais plataformas: Mac OS X, Linux e Windows. Além de conhecer algumas ferramentas de edição do código Ruby. Atualmente o Ruby se encontra na versão 1.9, que é totalmente estável e pronta para ser utilizada em ambientes de produção. Porem nosso tutorial será para a instalação do Ruby 1.8.7, que ainda é a versão mais utilizada. Vamos optar por esta versão pois como estamos em momento de transição da linguagem, é mais fácil para os iniciantes encontrarem material na internet, livros e código de terceiros que ainda não estão na versão mais atual. Mac OS X Vamos começar pelo mais simples, o sistema operacional da Apple. Em um esforço de tornar o Mac OS uma excelente plataforma de desenvolvimento, a Apple já inclui o Ruby, Rails e diversas outras bibliotecas (chamadas de Gems) em seu sistema. Não é necessário instalar nada, apenas fazer as devidas atualizações. Primeiro vamos atualizar o RubyGems, que é algo semelhante a um gerenciador de pacotes mas voltado exclusivamente para bibliotecas Ruby de terceiros. Abra o Terminal que se encontra em Applications/Utilities e execute: sudo gem update --system Agora podemos atualizar as Gems. O Rails é uma Gem, então com o comando baixo também baixamos e atualizamos o Rails para sua última versão (atualmente 2.3.5): sudo gem update Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 8 Curso online de Ruby On Rails Linux Para a instalação do Ruby no Linux utilizamos os gerenciadores de pacote que acompanham o sistema. Estou utilizando o Ubuntu 9.10 Karmic Koala. Em Applications/Acessories/Terminal execute os dois comandos abaixo: sudo apt-get update sudo apt-get dist-upgrade O comando acima apenas atualiza o nosso Ubuntu. Agora é hora de instalar o Ruby, mas como algumas gems (bibliotecas de terceiros) importantes precisam ser compiladas é necessário que você execute o comando abaixo: sudo apt-get install build-essential Com o “campo preparado” podemos instalar o Ruby: sudo apt-get install ruby ri rdoc mysql-server libmysql-ruby ruby1.8-dev irb1.8 libdbd-mysql-perl libdbi-perl libmysql-ruby1.8 libmysqlclient15off libnetdaemon-perl libplrpc-perl libreadline-ruby1.8 libruby1.8 mysql-client-5.1 mysqlcommon mysql-server-5.1 rdoc1.8 ri1.8 ruby1.8 irb libopenssl-ruby libopensslruby1.8 libhtml-template-perl mysql-server-core-5.1 libmysqlclient16 libreadline5 psmisc Parece muita coisa porém apenas 4 destes pacotes são obrigatórios, mas já estou instalando os que provavelmente você irá utilizar no dia a dia do desenvolvimento Ruby. Um dos pacotes instala o mysql, caso você ainda não o tenha feito ele irá pedir para escolher uma senha. Concluído o passo acima, agora precisamos instalar o RubyGems, que não vem por padrão no pacote. Execute os comandos a baixo, um a cada vez: wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz tar xvzf rubygems-1.3.5.tgz cd rubygems-1.3.5 sudo ruby setup.rb Agora você pode remover o arquivos de instalação com: rm -rf rubygems-1.3.5.tgz rubygems-1.3.5/ Agora é necessário criar alguns links para que o comando gem esteja acessível de qualquer local do sistema: Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 9 Curso online de Ruby On Rails sudo sudo sudo sudo sudo ln ln ln ln ln -s -s -s -s -s /usr/bin/gem1.8 /usr/local/bin/gem /usr/bin/ruby1.8 /usr/local/bin/ruby /usr/bin/rdoc1.8 /usr/local/bin/rdoc /usr/bin/ri1.8 /usr/local/bin/ri /usr/bin/irb1.8 /usr/local/bin/irb Agora basta executar sudo gem install rails Windows Para o windows vamos utilizar um instalador, já que o sistema operacional não possui um compilador GCC e nem um gerenciador de pacotes. Para solucionar este problema do sistema operacional existem vários projetos que já compilam o Ruby para o Windows. O mais famoso é Ruby One Click Installer, basta acessar o site do projeto (http://rubyinstaller.org/) e fazer download do arquivo ruby186-27_rc2.exe. Também existe a versão para Ruby 1.9 mas como eu disse anteriormente, vamos instalar o 1.8. Basta executar o arquivo, e avançar até concluir a instalação, porém é muito importante que na tela de escolha dos componentes (choose components) você não se esqueça de marcar a opção Enable RubyGems. Para o restante da instalação não é necessário mudar nada. Mas existe o pequeno porem que o One Click Installer instala o Ruby 1.8.6. Se você desejar atualiza-lo para o 1.8.7 acesse o site do Ruby em Downloads (http://www.ruby-lang.org/en/downloads/) e baixe o Ruby 1.8.7 binário, em seguida descompacte-o na pasta onde o Ruby One Click Installer colocou o Ruby, sobre-escrevendo seu conteúdo. Agora precisamos instalar o Rails. Abra o Prompt do MS-DOS( iniciar/executar/ cmd ) e digite: gem update --system Depois de atualizado o RubyGems vamos atualizar as gems o One Click já trouxe instalado, execute: Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 10 Curso online de Ruby On Rails gem update Agora é hora de instalar o Rails: gem install rails Concluido este passo também precisamos instalar o SQLite, que para facilitar prototipagem rápida, é o banco escolhido por padrão pelo Rails. Baixe os arquivos binários para windows sqlite-XXXX.zip e sqlitedll-XXXX.zip (onde XXXX é a versão) em http://www.sqlite.org/download.html e descompacte ambos os arquivos em c:\windows\system32 e execute o comando abaixo no prompt: gem install sqlite3-ruby -v=1.2.5 --no-ri --no-rdoc Concluindo o passo acima tanto o Ruby quanto o Rails estarão instalados. Também existem outras formas de instalação no Windows, e uma que merece ser lembrada é o projeto brasileiro Easy-Rails (http://rubyforge.org/projects/ easy-rails/) que permite instalar Ruby e o Rails apenas descompactando um arquivo, o que torna o projeto perfeito para instalação em faculdades, laboratórios ou até mesmo carregar o eco-sistema Ruby no pendrive. Testando a Instalação Depois de instalado o Ruby e Rails, podemos começar os estudos. Execute os comandos abaixo no console: ruby -v A resposta será versão do Ruby que acabamos de instalar, você pode também checar a versão do Rails com o comando rails -v . Para testes com a linguagem, o Ruby possui o IRB, um console interativo. Basta digitar irb no console, como abaixo: Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 11 Curso online de Ruby On Rails Para sair do IRB digite quit ou exit. Agora vamos criar o primeiro aplicativo Rails, também no console digite o comando abaixo: rails nome_do_projeto Se você instalou tudo corretamente o Rails vai gerar uma série de arquivos dentro da pasta do nome_projeto que você escolheu. Navegue para dentro desta pasta e digite: ruby script/server Como no Rails não é necessário instalar um servidor web para começar a desenvolver, o que o comando acima faz é iniciar o servidor que já vem por padrão no Ruby e que o Rails tira proveito. No navegador acesse http://localhost:3000/ e você verá algo como abaixo: Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 12 Curso online de Ruby On Rails Editores e IDE’s Agora que já temos o Ruby e o Rails instalados, só precisamos de uma forma de editar o código fonte de nossos projetos. Qual ferramenta utilizar é um tema que sempre gera bastante discussão, pois diferente de outras linguagens o Ruby não exige o uso de uma IDE. No desenvolvimento Ruby, a única coisa que é realmente essencial é uso do console para fazer chamadas simples como fizemos acima. No mundo Ruby o uso de IDE’s não é comum pois como a linguagem é bem simples, você não terá dificuldades para decorar os comandos e conhecer a API do Ruby. Outro fator que diminui a popularidade de IDE’s é que por ser uma linguagem interpretada não é necessário compilar e nunca será possível conseguir um auto-complete perfeito por ser dinâmica. IDE’s no mundo Ruby também perdem o valor rapidamente pois tanto a linguagem como os frameworks estilo o Rails são atualizados com frequencia, o que faz com que as IDE’s parem de funcionar. Mas o que é mais importante entender que principalmente para o iniciantes as IDE’s atrapalham o aprendizado já que abstraem a necessidade de usar Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 13 Curso online de Ruby On Rails console, criando wizards que fazem o mesmo que os comandos simples que executamos no terminal, tornando o desenvolvedor dependente da IDE e sem entender o que realmente está acontecendo. O que a maioria dos Rubistas mais experientes utilizam são editores de textos mais robustos que permitem colorização, snippets e automatização de tarefas. Para usuários do Mac OS X recomendo o uso do Textmate, mas também são populares o Emacs, GVim e GEdit. No Linux os mais utilizados são GEdit, GVim e Emacs. Para os usuários do Windows recomendo os mesmos navegadores (GEdit, GVim e Emacs), também existe o E-TextEditor que é muito bom. A opção mais simples e que funciona em qualquer um dos sistemas operacionais é o GEdit com o plugin brasileiro GMate, basta baixar o GEdit em . E para mais informações sobre o GMate acesse: http://blog.siverti.com.br/ gmate/ e para download http://github.com/lexrupy/gmate/tarball/master (instruções de instalação no arquivo Readme) Mas se você não abre mão de uma IDE a mais recomendada é o RubyMine (http://www.jetbrains.com/ruby/) mas também pode ser usado o Netbeans, Aptana ou Eclipse. A Linguagem Classes, Objetos e Variáveis Considerando que o Ruby é completamente orientado a objetos, nada mais apropriado que começar nossa exploração do mesmo por essa parte. A primeira coisa que precisamos no nosso processo de compreensão do Ruby é entender como variáveis funcionam. No Ruby, como na maior parte das linguagens orientadas a objeto, as variáveis são simplesmente referências a objetos. Veja o exemplo abaixo: irb(main):001:0> a = 1 => 1 irb(main):002:0> a = "1" => "1" Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 14 Curso online de Ruby On Rails No exemplo acima, atribuímos o valor inteiro 1 à variável a e depois atribuímos à mesma variável, o valor “1”, que é uma seqüência de caracteres. Isso, e o fato de que nenhum erro ocorreu, demonstram duas coisas sobre o Ruby. Primeiro variáveis simplesmente apontam para os valores atribuídos à mesma, e, por causa disso, podem ser re-atribuídas de acordo com necessidade; segundo variáveis não precisam ser declaradas. Um exemplo posterior poderia ser: irb(main):001:0> => 1 irb(main):002:0> => Fixnum irb(main):003:0> => "1 " irb(main):004:0> => String a = 1 a.class a = "1 " a.class Note que mesmo tipos primitivos como o número inteiro 1 são membros de uma classe—no caso Fixnum, que é a classe que define números com representação fixa. Considere agora o seguinte trecho de código: irb(main):001:0> 1.class => Fixnum irb(main):002:0> 1.class.class => Class irb(main):003:0> 1.class.superclass => Integer irb(main):004:0> Note que 1 é uma instância da classe Fixnum. A classe Fixnum, por sua vez, é também um objeto, uma instância da classe Class, que define todas as classes em Ruby. Class é chamada a metaclasse de Fixnum, ou seja, é uma classe que descreve uma classe. Na terceira linha temos outro conceito de orientação a objetos que é a superclasse de uma classe, ou seja, a classe da qual a mesma é derivada. No caso de Fixnum, temos a seguinte hierarquia: Object => Numeric => Integer => Fixnum. Esses dois conceitos, metaclasses e superclasses, são importantes em qualquer linguagem orientada a objeto e precisam ser compreendidos por Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 15 Curso online de Ruby On Rails qualquer programador. Para entender melhor esses conceitos, responda as seguintes questões: Exercício 1 1. Qual é a classe base de todos objetos Ruby? 2. Qual é a metaclasse base de todas as classes Ruby? Agora que já vimos um pouco de variáveis em Ruby, podemos começar a utilizá-las com maior confiança. Como mencionado anterior e demonstrado acima, todo valor em Ruby é uma instância de uma classe e possui os métodos próprios dessa classe. Por exemplo: irb(main):001:0> => "1" irb(main):002:0> => 2 irb(main):003:0> => 2 irb(main):004:0> => 1 irb(main):005:0> => 3 1.to_s 1 + 1 1.+(1) -1.abs "123".length No exemplo acima, temos várias invocações de métodos de determinados objetos. O primeiro método invocado, to_s, converte um valor númerico em uma string correspondente. O segundo exemplo é ainda mais interessante. Note que fizemos uma operação, somando dois números. Mas, como podemos ver logo abaixo, a operação é simplesmente uma invocação de um método do objeto. Obviamente que, para uso diário, utilizaremos a primeira sintaxe. É importante, porém, compreender que isso é válido para basicamente todos os métodos do Ruby e que isso pode ser usado em suas próprias classes. Uma maneira fácil de visualizar os métodos que uma classe possui é chamar o seu método methods, como pode ser visto abaixo: ~$ irb irb(main):001:0> 1.methods => ["%", "inspect", "<<", "singleton_method_added", "&", "clone", ">>", "ceil", "public_methods", "instance_variable_defined?", "div", "equal?", "freeze", "times", "*", "+", "to_i", "methods", "respond_to?", "-", "upto", "between?", "prec", "round", "/", "method", "dup", "instance_variables", "__id__", "divmod", "chr", "succ", "|", "eql?", "integer?", "~", "id", "to_f", "singleton_methods", Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 16 Curso online de Ruby On Rails "send", "prec_i", "taint", "truncate", "to_int", "frozen?", "instance_variable_get", "__send__", "^", "instance_of?", "modulo", "to_a", "object_id", "+@", "zero?", "-@", "type", "**", "<", "protected_methods", "<=>", "instance_eval", "==", "prec_f", "quo", ">", "===", "step", "id2name", "size", "instance_variable_set", "kind_of?", "remainder", "extend", ">=", "nonzero?", "next", "to_s", "<=", "coerce", "hash", "floor", "class", "tainted?", "=~", "private_methods", "display", "fdiv", "nil?", "untaint", "downto", "to_sym", "[]", "is_a?", "abs"] Esses são todos os métodos públicos compartilhados pelas instâncias da classe Fixnum. Como classes podem possuir métodos públicos, protegidos e privados, a distinção pode ser obtida invocando os métodos public_methods, protected_methods e private_methods de uma instância qualquer. Incidentemente, classes são objetos também, com seus próprios métodos. Você pode observar isso invocando o método acima em uma classe, usando, por exemplo: ~$ irb irb(main):001:0> String.public_methods => ["inspect", "private_class_method", "const_missing", "clone", "public_methods", "public_instance_methods", "instance_variable_defined?", "method_defined?", "superclass", "equal?", "freeze", "included_modules", "const_get", "autoload?", "methods", "respond_to?", "module_eval", "class_variables", "method", "dup", "protected_instance_methods", "instance_variables", "public_method_defined?", "__id__", "eql?", "const_set", "id", "singleton_methods", "send", "class_eval", "taint", "frozen?", "instance_variable_get", "include?", "private_instance_methods", "__send__", "instance_of?", "private_method_defined?", "to_a", "object_id", "name", "type", "new", "<", "protected_methods", "instance_eval", "<=>", "==", ">", "===", "instance_variable_set", "kind_of?", "extend", "protected_method_defined?", "const_defined?", ">=", "ancestors", "to_s", "<=", "public_class_method", "autoload", "allocate", "hash", "class", "instance_methods", "tainted?", "=~", "private_methods", "class_variable_defined?", "display", "nil?", "instance_method", "untaint", "constants", "is_a?"] Aqui cabe uma explicação sobre uma diferença do Ruby para outras linguagens orientadas a objetos. Métodos públicos são métodos acessíveis a todo o programa. Métodos protegidos são acessíveis somente a instâncias da própria classe e subclasses da mesma. Em Ruby, porém, métodos privados possuem uma distinção sutil: eles somente podem ser chamados com um receptor explícito, ou seja, dentro do próprio objeto. Isso significa que subclasses podem também chamar os métodos privados de sua superclasse, mas somente dentro do seu próprio contexto de execução. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 17 Curso online de Ruby On Rails Objetos, como instâncias de classes, podem ser criados implicitamente ou explicitamente em Ruby. Acima, vimos alguns exemplos de criação implícita, que é comum a todos os tipos primitivos. A criação explícita, porém, é feita através da invocação do método new: ~$ irb irb(main):001:0> a = "Uma string qualquer" => "Uma string qualquer" irb(main):002:0> b = String.new("Uma string qualquer") => "Uma string qualquer" irb(main):003:0> a == b => true irb(main):004:0> require 'date' => true irb(main):005:0> d = Date.new(2007, 1, 1) => #<Date: 4908203/2,0,2299161> irb(main):006:0> d.day => 1 irb(main):007:0> d.year => 2007 Note que nas primeiras declarações criamos uma string de maneira implícita e de maneira explícita. Uma comparação entre as duas revela que não há diferença na criação, ou seja, a criação implícita é essencialmente o mesmo que uma chamada ao método new seguida de uma atribuição. No exemplo seguinte, temos a criação de um objeto que não possui criação implícita. Note também que o objeto não faz parte do núcleo do Ruby, mas é implementado em uma biblioteca externa que é adquirida para o contexto atual através do método require. Esse método, embora seja invocado aparentemente sem um objeto receptor, é na verdade um método do módulo Kernel, incluindo na classe Object, que provê uma série de métodos comuns para o ambiente de execução Ruby. Veremos mais sobre módulos em seções seguintes. Como podemos notar de tudo o que foi visto acima, o Ruby é realmente uma linguagem orientada a objetos em toda a sua extensão. Todo valor criado é uma instância de uma classe qualquer, mesmo as próprias classes. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 18 Curso online de Ruby On Rails Exercício 2 1. O Ruby possui um método chamado object_id, comum a todas as classes e objetos. O que esse método faz? 2. Faça um teste, criando duas variáveis inteiras atribuindo o mesmo valor númerico. Compare os object_id das mesmas. Qual é o resultado? 3. Faça o mesmo teste com duas variáveis String. Qual é o resultado agora? Agora que trabalhamos um pouco com os conceitos básicos de classes, objetos e variáveis, é hora de criar as nossas próprias classes, experimentando um pouco mais com o sistema de objetos do Ruby. Criar uma classe é bem simples em Ruby. Basta fazer o seguinte: class Entity def initialize(type, name) @type = type @name = name end end O código acima define uma classe chamada Entity que possui um método chamado initialize. Esse método possui uma conotação especial em Ruby, sendo o método que é invocado quando a instância de uma classe é criada (também conhecido como construtor). Vejamos isso em um exemplo: samwise = Entity.new(:hobbit, "Samwise Gamgi") gandalf = Entity.new(:istari, "Galdalf, the Grey") O código acima cria duas instâncias da classe Entity, atribuindo os parâmetros a variáveis de instância da classe (identificadas pelo sinal @ na frente dos seus nomes). Note que new é usado e não initialize, sendo que este último é invocado automaticamente. Esse é um detalhe de implementação do Ruby, sendo que o método initialize é automaticamente marcado com private. Explorando essas classes no irb, teríamos algo assim: irb(main):001:0> samwise = Entity.new(:hobbit, "Samwise Gamgi") => #<Entity:0xb7d634c4 @name="Samwise Gamgi", @type=:hobbit> Caso você não queira ficar colando o código a todo momento, salve um arquivo com um nome qualquer e a extensão .rb e use o método load para carregar esse arquivo, lembrando que load requer o nome completo do arquivo a carregar, incluindo a extensão. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 19 Curso online de Ruby On Rails Note que o Ruby fornece uma representação interna do objeto para fácil visualização. Na representação acima, a classe do objeto é exibida, seguida de seu endereço em memória. Depois, temos as variáveis internas do objeto com seus valores. Você deve estar se perguntando o que os dois pontos na frente de um nome—como :hobbit, por exemplo—significam. Nomes atribuídos assim são chamados de símbolos e veremos mais sobre eles adiante. Por hora, basta dizer que são representações eficientes de um valor qualquer. Note que se você tentar extrair o valor de uma variável de instância acima, você verá um erro. Por exemplo: irb(main):001:0> samwise.name NoMethodError: undefined method `name' for #<Entity:0xb7d634c4 @name="Samwise Gamgi", @type=:hobbit> from (irb):11 from :0 Variáveis de instância são automaticamente internas(privadas) e você só pode extrair o valor das mesmas publicamente criando um método específico para isso. Falando em métodos, podemos criar um método para a nossa classe para ver com os mesmos funcionam. Para isso, vamos substituir a inconveniente representação textual acima por uma de nosso interesse. Isso é feito criando um método chamado to_s, que já mencionamos anteriormente. Esse método converte um objeto qualquer em sua representação textual. Todos objetos em Ruby possuem esse método, embora sua implementação inicial seja bem limitada. Vejamos para o objeto acima: irb(main):001:0> samwise.to_s => "#<Entity:0xb7d634c4>" Podemos sobrescrever o método assim: class Entity def initialize(type, name) @type = type @name = name end def to_s "#{@name} is a #{@type}" end end Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 20 Curso online de Ruby On Rails O código acima apresenta algumas características interessantes. Primeiro, ele retorna a representação textual do objeto, mas sem invocar qualquer expressão de retorno. Ruby possui, realmente, uma expressão return, mas a mesma não precisa ser usada na maior parte dos casos. Isso acontece porque qualquer expressão em Ruby retorna automaticamente um valor. Se o valor não é explicitamente retornado, o valor nil é usado implicitamente. Isso significa que um método retorna o resultado de sua última expressão, sem necessidade de chamar return. No método acima, estamos retornando também uma string, usando o que é chamado de interpolação de valores. Qualquer expressão entre os delimitadores #{} dentro de uma string será executada e seu valor representacional retornado—isto é—o método to_s do valor resultante é invocado automaticamente. Veja o resultado do método acima: irb(main):001:0> samwise = Entity.new(:hobbit, "Samwise Gamgi") => #<Entity:0xb7dc0958 @name="Samwise Gamgi", @type=:hobbit> irb(main):002:0> samwise => #<Entity:0xb7dc0958 @name="Samwise Gamgi", @type=:hobbit> irb(main):003:0> samwise.to_s => "Samwise Gamgi is a hobbit" irb(main):004:0> "#{samwise}" => "Samwise Gamgi is a hobbit" irb(main):005:0> puts samwise Samwise Gamgi is a hobbit => nil Note que to_s agora é usado implicitamente onde uma representação textual de um objeto é exigida. Uma pequena exceção é a exibição do objeto no irb, onde to_s não é invocado diretamente para prover detalhes de implementação. Note que no final, ao invocarmos puts, o valor é impresso na tela e nil é retornado. Isso ocorre porque puts envia seus parâmetros à saída padrão e retorna nil, ou seja, não retorna nada específico. Voltando à questão dos atributos, se quisermos torná-los manipuláveis, podemos usar a seguinte implementação: class Entity def initialize(type, name) @type = type @name = name end def to_s "#{@name} is a #{@type}" end Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 21 Curso online de Ruby On Rails def name @name end def type @type end def name=(value) @name = value end def type=(value) @type = value end end Isso permite o seguinte código: irb(main):001:0> samwise = Entity.new(:hobbit, "Samwise Gamgi") => #<Entity:0xb7da02d4 @name="Samwise Gamgi", @type=:hobbit> irb(main):002:0> samwise.name => "Samwise Gamgi" irb(main):003:0> samwise.type => :hobbit irb(main):004:0> samwise.name = "Samwise, the Brave" => "Samwise, the Brave" irb(main):005:0> samwise.name => "Samwise, the Brave" irb(main):006:0> samwise.to_s => "Samwise, the Brave is a hobbit" Note que agora temos métodos que podemos usar para obter ou mudar o valor de um atributo do objeto. Os métodos que mudam o valor possuem um sinal de igual (=) em seu nome e são usados automaticamente pelo Ruby em caso de atribuição como o exemplo demonstra. Exercício 3 1. Existe alguma diferença entre “objeto.atributo = valor” e “objeto.atributo=(valor)”? 2. Repetir o código acima para cada atributo de um objeto seria tedioso. Existe uma forma do Ruby de evitar a repetição? Obviamente, pela maneira como atributos são implementados em Ruby, a representação externa não precisa corresponder à interna. É o caso da classe Date por exemplo, que guarda uma representação interna da data informada, Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 22 Curso online de Ruby On Rails mas permite que as instâncias seja manipuladas em termos de diversos atributos. Como classes também são instâncias, elas podem ter métodos e atributos. Digamos que precisamos saber todas os tipos já usados em entidades. Podemos ter algo assim: class Entity @@types = [] def initialize(type, name) @type = type @name = name @@types << @type unless @@types.include?(@type) end # ... def self.types @@types end end A implementação acima cria uma variável de classe chamada types e registra, a cada criação, se um novo tipo foi adicionado ao “universo” do mesmo. A linha final do método initialize executa o seguinte: adiciona o type informado à variável types a menos (unless) que o mesmo já exista na lista. Note também o uso de self para especificar que o método pertence à classe e não a uma instância (estamos criando um método de classe, semelhante aos métodos static do Java). Um exemplo de uso seria o seguinte: irb(main):001:0> samwise = Entity.new(:hobbit, "Samwise Gamgi") => #<Entity:0xb7d94ca4 @name="Samwise Gamgi", @type=:hobbit> irb(main):002:0> Entity.types => [:hobbit] irb(main):003:0> gandalf = Entity.new(:istari, "Galdalf, the Grey") => #<Entity:0xb7d8cba8 @name="Galdalf, the Grey", @type=:istari> irb(main):004:0> Entity.types => [:hobbit, :istari] irb(main):005:0> frodo = Entity.new(:hobbit, "Frodo Baggins") => #<Entity:0xb7d86bb8 @name="Frodo Baggins", @type=:hobbit> irb(main):006:0> Entity.types => [:hobbit, :istari] Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 23 Curso online de Ruby On Rails Dois detalhes a serem observados aqui. Primeiro, variáveis de classes são compartilhadas entre todas subclasses e a própria classe, o que significa que se você mudá-la em uma subclasse, o valor será mudado, por assim dizer, em todas outras, já que meramente aponta para a mesma variável. Esse é um detalhe em que Ruby é diferente de outras linguagens. Segundo, variáveis de classe usam @@ antes do seu nome. Se você declarar uma dessas variáveis usando somente @, um caso especial de variável da instância da classe será criado, com semântica diferente. Essa variável pertence somente àquela instância e não é compartilhada. Podemos agora nessa seção especificar o controle de acesso de uma classe. Veja o seguinte: class Test public def method1 end protected def method2 end private def method3 end end Ao contrário da maioria das linguagens orientadas a objeto, em Ruby public, protected e private não simplesmente marcadores sintáticos. são métodos que modificam a classe dinamicamente e mantém o escopo de acesso até que outro escopo seja invocado. A classe acima poderia ser especificada assim com o mesmo resultado: class Test def method1 end def method2 end def method3 end public :method1 protected :method2 Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 24 Curso online de Ruby On Rails private :method2 end Herança simples em Ruby é bastante trivial: class B < A end A declaração acima indica que a classe B herda os métodos da classe A. Variáveis de classe, variáveis de instância, e variáveis de instância de classe seguem as regras descritas anteriormente. O mesmo para métodos públicos, privados e protegidos. No momento, não entraremos em detalhes sobre a herança porque ela é usada minimamente da forma acima em Ruby, servindo mais para propagação rápida de tipos. O método mais usado para estender classes díspares em Ruby é chamado de mixin e será assunto de uma aula próxima. Exercício 4 1. O que acontece se um método de uma superclasse for redeclarado em uma subclasse? 2. Como em Ruby, pode-se invocar o método de uma superclasse em uma subclasse ? Respostas Exercício 1 1. Object 2. Class Exercício 2 1. Retorna um identificador numérico único para o objeto. 2. Temos o mesmo object_id para cada variável, isso ocorre pois números inteiros são Fixnum’s com o mesmo id. 3. Cada objeto possui um object_id diferente pois cada instância da class String faz referência para uma posição diferente. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 25 Curso online de Ruby On Rails Exercício 3 1. Não 2. Poderia ser utilizado o método attr_accessor para criar getter e setter para os valores passados. Como abaixo: attr_acessor :name, :type Exercício 4 1. Este método será sobre-escrito. 2. Basta chamar o método normalmente de dentro da subclasse. Criado por e-Genial Soluções Inteligentes – Todos os direitos reservados. 26