O Ruby on Rails está inovando o desenvolvimento da Web. Começaremos com uma pincelada nas tecnologias subjacentes:
- Ruby é uma linguagem de script livre, simples, direta, extensível, portátil e interpretada para programação orientada a objetos rápida e fácil, como Perl, que possui muitos recursos para o processamento de arquivos de texto e executa tarefas de gerenciamento de sistema.
- Rails é uma pilha completa, a estrutura da Web de software livre no Ruby para criar aplicativos em tempo real mais facilmente e com menos código.
Ser uma estrutura de pilha completa significa que todas as camadas no Rails são criadas para funcionarem juntas, de modo que você não precise repetir operações e possa usar uma única linguagem do começo ao fim do processo. Com o Rails, tudo (de modelos para fluxos de controle até lógicas de negócios) é criado em Ruby. O Rails favorece a reflexão e as extensões de tempo de execução em arquivos de configuração e anotações.
Este artigo detalha os componentes do Rails e mostra como ele funciona.
O primeiro item para entender sobre o Rails é sua arquitetura model/view/controller (MVC). Embora essa abordagem não seja exclusiva do Rails -- ou mesmo para aplicativos da Web em oposição a outros programas -- o Rails fornece uma lógica muito clara e focada no MVC. Se você não conhece a abordagem MVC, o Rails se torna menos útil do que quando se segue seu paradigma.
A parte de modelo de um aplicativo Rails é principalmente o banco de dados subjacente que ele utiliza. Na verdade, em muitos casos, um aplicativo Rails é apenas uma forma direta de executar manipulações de dados em um Sistema de Gerenciamento de Banco de Dados Relacional (RDBMS).
Um componente central do Rails é a classe ActiveRecord, que mapeia tabelas relacionais para objetos Ruby e, através delas, para dados manipulados por controladores, como mostrado nas visualizações. Os aplicativos Rails, especialmente, tendem a utilizar o banco de dados MySQL ubíquo, mas existem ligações para diversos outros RDBMSs, inclusive para o IBM® DB2®.
Se desejar, é possível incluir código Ruby para executar validação extra dentro de um modelo de aplicativo, impingir relacionamentos de dados ou acionar outras ações. Os arquivos do Ruby dentro de um diretório app/models/ do aplicativo podem chamar uma variedade de métodos de validação de ActiveRecord. No entanto, também é possível deixar o código de modelo como um stub, bem como contar apenas com as limitações do RDBMS que mantêm os dados. Por exemplo, o aplicativo que eu desenvolvo neste exemplo contém apenas este esboço do código de modelo (pelo menos inicialmente):
Lista 1. Esboço de Modelo app/models/contact.rb
class Contact < ActiveRecord::Base end |
Os controladores transportam a lógica de seu aplicativo de forma abstrata. Ou seja, os scripts Ruby no diretório app/controllers/ do aplicativo carregarão os dados do modelo em variáveis, os salvarão novamente e os manipularão. Mas os controladores não estão preocupados com o modo no qual os dados são concretamente apresentados e inseridos pelos usuários. No paradigma MVC geral, eles podem permitir que vários estilos de usuários interajam com o mesmo controlador: uma GUI nativa, uma interface da Web e uma interface de fala para pessoas com deficiência visual podem todas interagir com o mesmo controlador.
O Rails já não é tão generalizado assim; ele, por sua vez, tem foco mais restrito no fornecimento e coleta de dados dentro de páginas da Web. Apesar disso, é possível modificar o layout dessas páginas da Web -- cores, fontes, tabelas, folhas de estilo, etc. -- independentemente do código do controlador.
As visualizações do Rails ocorrem onde deixamos o código Ruby. O Rails contém uma linguagem de modelo muito boa para arquivos .rhtml, que combina HTML puro com código Ruby embarcado. A aparência muito plana de uma tela de aplicativo Rails geralmente é controlada pelas folhas de estilo CSS. O formato .rhtml é um aperfeiçoamento de HTML. Na verdade, um arquivo HTML simples por si só já é um modelo RHTML válido, mas não há muita vantagem na omissão do controle de script que o RHTML fornece a você.
RHTML é um verdadeiro formato de modelo -- não simplesmente uma forma de código embarcado em HTML -- e esta é uma abordagem mais poderosa. Se você estiver familiarizado com PHP, pense no contraste entre o próprio PHP e os modelos Smarty. Ou seja, o script embarcado apenas combina o código com HTML não-interpretado; a parte do código ainda é responsável por emitir instruções print para levar informações ao cliente.
Em contraste, um mecanismo modelo inclui um conjunto customizado de tags para HTML, que permite que você expresse condições, loops e outras lógicas como parte da marcação HTML aprimorada.
As ferramentas que o Rails fornece são basicamente um conjunto de geradores de códigos. Eu gosto muito mais dessa abordagem do que a de um ambiente de desenvolvimento que me força a usar um espaço de trabalho e um IDE rígidos. O Rails não pode ser totalmente customizado, mas, apesar disso, poupa muito mais trabalho do que a programação manual -- ou pelo menos facilita as partes que exigem codificação manual, fornecendo estruturas "para maior liberdade."
O conceito de fornecer estrutura é uma noção central no Rails. Aplicativos muito simples pode evitar, quase totalmente, a codificação customizada, permitindo que o Rails gere dinamicamente páginas HTML clientes no momento da execução. Uma geração de código única cria apenas a estrutura bruta; subsequentemente é possível gerar mais controladores, visualizações e modelos específicos que podem ser customizados. Mas não é necessário gerar muitos para começar.
O Rails conta com uma organização de arquivos fixa e comum, embora ela seja relativamente rígida. Você só não se familiarizará com o ambiente Rails se tentar forçar outras organizações de códigos e arquivos. Novamente, eu não vejo razão para não continuar com a organização que o Rails fornece; quase sempre, ela "se adequa à sua lógica" (como dizem os fãs do Ruby). Por exemplo, os nomes de diretórios e sua organização serão, provavelmente, muito parecidos com o que você escolheria se estivesse criando uma estrutura do zero (pelo menos se você pensar como o Ruby).
Vários tutoriais estão disponíveis no Web site do Ruby on Rails, que é possível percorrer criando um aplicativo Rails simples (consulte Recursos). O aplicativo de amostra aqui se assemelha a eles, já que há uma forma específica de criar um aplicativo Rails. Devido ao tamanho relativamente pequeno desta introdução, eu recomendo um desses tutoriais mais longos para que você possa se inteirar mais no assunto.
O aplicativo de amostra é um catálogo de endereços básico. Ele demonstra as etapas gerais para a criação de um aplicativo:
- Gerar o modelo (no qual você cria uma tabela e banco de dados MySQL).
- Gerar o aplicativo (inclui a geração de diretórios e códigos básicos).
- Executar o Rails (e configurar acesso ao banco de dados).
- Criar algum conteúdo (inclui a geração do modelo estrutural e do controlador e informações para o controlador usar a estrutura).
Vejamos detalhadamente cada etapa.
A primeira coisa que você precisa fazer para qualquer aplicativo é criar um banco de dados para seus dados. Tecnicamente, esta etapa não precisa ocorrer primeiro, mas precisa ocorrer anteriormente; é óbvio que é necessário criar um banco de dados antes de qualquer código de aplicativo, mesmo que o código seja gerado automaticamente. Assim, criaremos um banco de dados em MySQL e faremos um rascunho da primeira tabela dentro deste banco de dados. (Consulte outra documentação sobre como ter MySQL ou outro RDBMS em execução.)
Assumiremos que MySQL está instalado e disponível.
Lista 2. Criando uma Tabela e Banco de Dados MySQL
[~/Sites]$ cat AddressBook.sql CREATE DATABASE IF NOT EXISTS AddressBook; USE AddressBook; CREATE TABLE IF NOT EXISTS contacts ( id smallint(5) unsigned NOT NULL auto_increment, name varchar(30) NOT NULL default '', created_on timestamp(14) NOT NULL, updated_on timestamp(14) NOT NULL, PRIMARY KEY (id), UNIQUE KEY name_key (name) ) TYPE=MyISAM COMMENT='List of Contacts'; [~/Sites]$ cat AddressBook.sql | mysql |
Há algumas coisas a serem observadas nesta primeira tabela. Um ponto essencial é que cada tabela deve ter uma coluna id com exatamente esse nome. O Rails usa a coluna-chave primária id para tarefas de referência e manutenção de diversos registros. Os campos created_on e updated_on não são necessários, mas se você incluí-los, o Rails os manterá automaticamente "nos bastidores"; na maioria dos casos, o uso desses registros não causa danos. Assim, os únicos dados "reais" que você incluiu são um nome para seus contatos no catálogo de endereços.
Outro ponto "diferente" no Rails é que ele usa nomes simples e compostos para vários itens. Vários itens são renomeados entre versões simples e compostas, dependendo do uso e do contexto. Os nomes de tabelas devem usar o formato composto. Eu não testei palavras com plurais irregulares; palavras como datum e data podem "enganar" o Rails.
Gerando o Aplicativo AddressBook
Agora que você tem um banco de dados com o qual interagir, crie o aplicativo AddressBook. A primeira etapa é simplesmente executar o Rails para gerar os diretórios básicos e o código da estrutura:
Lista 3. Gerando Códigos e Diretórios Básicos
[~/Sites]$ rails AddressBook create create app/apis create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create components [...] create public/images create public/javascripts create public/stylesheets create script [...] create README create script/generate create script/server [...] |
Eu resumi a saída de Rails em execução; as linhas omitidas apenas o lembram dos diversos arquivos e diretórios que foram criados. Teste em seu sistema e procure por todos os arquivos criados. Eu mostrei alguns dos arquivos e diretórios mais importantes no código.
Depois de criar o diretório AddressBook/ e os filhos necessários, é necessário executar apenas uma configuração inicial vazia. Primeiro, configure o banco de dados modificando um arquivo de configuração YAML da seguinte forma:
Lista 4. Configurar Acesso ao Banco de Dados
[~/Sites]$ cd AddressBook [~/Sites/AddressBook]$ head -6 config/database.yml # depois de editar a implementação: adapter: mysql database: AddressBook host: localhost username: some_user password: password_if_needed |
Finalmente, é necessário servir os dados. O Rails vem com seu próprio servidor da Web com funções exclusivas, WEBrick, que é perfeitamente adequado para nossa experiência. Também é possível seguir as instruções no Web site do Ruby on Rails para configurar o Apache ou outros servidores para servir aplicativos Rails via FCGI (ou CGI simples, mas o CGI simples será lento).
Lista 5. Iniciando o Servidor WEBrick
[~/Sites/AddressBook]$ ruby script/server -d => Rails application started on http://0.0.0.0:3000 [2005-03-21 17:57:38] INFO WEBrick 1.3.1 [2005-03-21 17:57:38] INFO ruby 1.8.2 (2004-12-25) [powerpc-darwin7.8.0] |
As etapas anteriores são suficientes para permitir que você visualize uma página personalizada de boas-vindas na porta do WEBrick. Por exemplo, em meu sistema local, agora eu posso visualizar http://gnosis-powerbook.local:3000/. Mas será necessário gerar apenas mais código para manipular seu banco de dados customizado. É possível fazer isso com o script generate, que foi criado dentro do diretório de aplicativo AddressBook/:
Lista 6. Geração de Código do Controlador e Modelo de Estrutura
[~/Sites/AddressBook]$ ruby script/generate model contact
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/contact.rb
create test/unit/contact_test.rb
create test/fixtures/contacts.yml
[~/Sites/AddressBook]$ ruby script/generate controller contact
exists app/controllers/
exists app/helpers/
create app/views/contact
exists test/functional/
create app/controllers/contact_controller.rb
create test/functional/contact_controller_test.rb
create app/helpers/contact_helper.rb
|
Observe aqui que você deve usar um único contato comum em vez de vários contatos no nome de tabela correspondente.
Agora é necessário editar mais um arquivo gerado, apenas um pouco, para que o controlador use a estrutura:
Lista 7. Pedindo ao Controlador para Utilizar a Estrutura
[~/Sites/AddressBook]$ cat app/controllers/contact_controller.rb class ContactController < ApplicationController model :contact scaffold :contact end |
Agora é possível visualizar e modificar o conteúdo do seu banco de dados em uma URL como http://rails.server/contact/ (no caso do meu teste, ele é http://gnosis-powerbook.local:3000/contact/). Depois de inserir alguns dados, ele se assemelhará à Figura 1 e 2:
Figura 1. Listando Contatos
Figura 2. Editando Contato
O código anterior cria uma interface de trabalho completa para visualizar e modificar seu banco de dados, mas toda a formatação, apresentação e lógica de negócios (o que houver) serão feitas dinamicamente pelo Rails, sem nenhuma grande sofisticação. Para criar algo um pouco mais customizado, é necessário gerar mais código. O que precisamos agora é que o Rails crie explicitamente toda a estrutura que ele está gerando para que possamos customizá-la.
Lista 8. Geração de Código para Controlador e Visualização Explícitos
[~/Sites/AddressBook]$ ruby script/generate scaffold Contact
dependency model
[...]
create app/views/contacts
exists test/functional/
create app/controllers/contacts_controller.rb
create test/functional/contacts_controller_test.rb
create app/helpers/contacts_helper.rb
create app/views/layouts/contacts.rhtml
create public/stylesheets/scaffold.css
create app/views/contacts/list.rhtml
create app/views/contacts/show.rhtml
create app/views/contacts/new.rhtml
create app/views/contacts/edit.rhtml
|
Agora, há mais recursos com os quais trabalhar, assim, tente modificar alguns itens. (Observe que esse código voltou ao formato de vários contatos, por razões que ainda não são claras para mim; agora precisamos aceitá-las.) Tente alterar algumas cores e fontes no CSS:
Lista 9. Configurando as Folhas de Estilo em Cascata
[~/Sites/AddressBook]$ head -8 public/stylesheets/scaffold.css
body { background-color: #ffe; color: #338; }
body, p, ol, ul, td {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
}
td { border: 1px solid; }
a { color: #eef; background-color: #446; }
a:hover { color: #fff; background-color:#000; }
|
Agora que você tem o código, o que contacts_controller.rb faz? Nesta ação, isso fica mais explícito e configurável do que o contact_controller.rb que você viu no código anterior. Em parte, o controlador se assemelha a isto:
Lista 10. Controlador app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def list
@contacts = Contact.find_all
end
def show
@contact = Contact.find(@params['id'])
end
def create
@contact = Contact.new(@params['contact'])
if @contact.save
flash['notice'] = 'Contact was successfully created.'
redirect_to :action => 'list'
else
render_action 'new'
end
end
|
Como promessa, a tarefa principal de um controlador é carregar dados em variáveis. O objeto Contact é o mapeamento relacional de objetos ActiveRecord que o modelo fornece. As variáveis @contacts ou @contact são dados fornecidos em seu métodos adequados. Os métodos são referidos pelas URLs como http://rails.server/contacts/show/2 (isso mostra o contato com o id "2").
O controlador neste exemplo conecta-se por fim às visualizações, os arquivos RHTML que fazem uso dos valores de dados carregados nas variáveis pelo controlador. Por exemplo, aqui está parte da visualização list:
Lista 11. Visualização List app/views/contacts/list.rhtml
[...]
<% for contact in @contacts %>
<tr>
<% for column in Contact.content_columns %>
<td><%=h contact.send(column.name) %></td>
<% end %>
<td><%= link_to 'Show', :action => 'show', :id => contact.id %></td>
<td><%= link_to 'Edit', :action => 'edit', :id => contact.id %></td>
<td><%= link_to 'Destroy', :action => 'destroy', :id => contact.id %></td>
</tr>
<% end %>
[...]
|
O método ContactsController.list carrega a variável @contacts e as tags de controle de fluxo no RHTML escolhem os registros individuais da matriz.
O modelo inicial continha apenas um nome para um contato. Infelizmente, eu não tenho espaço neste artigo para expandir o modelo para incluir dados de contatos reais como números de telefones, endereços, emails, etc. Geralmente esses dados residem em uma tabela-filho com uma relação de chave estrangeira com os contatos da tabela . O modelo Rails indicaria a relação com o código customizado, algo como o seguinte:
Lista 12. Código Customizado app\models\phone.rb
class Phone < ActiveRecord::Base belongs_to :contact end |
Antes de agrupar, vamos alterar um pouco o modelo de dados e ver como isso afeta o aplicativo. Primeiro, inclua uma coluna:
Lista 13. Incluindo Dados first_met no Modelo
$ cat add-contact-date.sql USE AddressBook; ALTER TABLE contacts ADD first_met date; $ cat add-contact-date.sql | mysql |
Agora que você alterou o modelo subjacente, http://rails.server/contact/ -- a versão "oculta" da estrutura -- basta ajustar, sem esforço algum, sua parte. O controlador e a visualização são totalmente automatizados com base no modelo. Mas a versão do aplicativo em http://rails.server/contacts/ , com nossos arquivos alterados, não é tão automática.
A visualização de list consulta automaticamente toda as colunas, independentemente do que sejam, incluindo Contact.content_columns como parte do loop do modelo. Mas outras visualizações, como edit já foram geradas e é necessário incluir seus novos campos de dados. Por exemplo:
Lista 14. Visualização Edit app/views/contacts/edit.rhtml
<h1>Editing contact</h1> <%= error_messages_for 'contact' %> <%= start_form_tag :action => 'update' %> <%= hidden_field 'contact', 'id' %> <p><label for="contact_name">Name</label><br/> <%= text_field 'contact', 'name' %></p> <p><label for="first_met">Known Since</label><br/> <%= date_select "contact", "first_met", :use_month_numbers => false %></p> <input type="submit" value="Update" /> <%= end_form_tag %> <%= link_to 'Show', :action => 'show', :id => @contact.id %> | <%= link_to 'Back', :action => 'list' %> |
Portanto, com o que seu aplicativo alterado se assemelha? Ele não é muito diferente do padrão, mas suas modificações podem ser vistas nas Figuras 3 e 4:
Figura 3. Contatos de Lista Modificados
Figura 4. Contatos de Edição Modificados
O Rails fornece uma maneira rápida de desenvolver aplicativos da Web flexíveis; essa introdução apenas mencionou brevemente como é trabalhar com o Rails. A estrutura completa contém muitas classes úteis e métodos para cuidar das ações mais utilizadas nos aplicativos baseados na Web.
O melhor do Rails é que ele estimula uma "lógica própria", pois é fornecido completo, com todos os códigos de suporte que você precisa. Isso é um adicional sobre outros kits de ferramentas e estruturam que fornecem apenas materiais básicos com os quais trabalhar. O desenvolvimento do Rails oferece a você uma forma clara, uma ideia praticamente formada, para o funcionamento total do aplicativo da Web.
-
"Deploy an application with Cerise Web server" (developerWorks, fevereiro de 2005) mostra como criar um aplicativo guestbook da Web com os servidores da Web Cerise e Ruby.
-
A home page para o Ruby on Rails é o local ideal para obter tutoriais de apresentação, guias e fontes e documentações que podem ser transferidas por download.
-
Para uma lista de bancos de dados aos quais o Ruby on Rails oferece suporte, incluindo IBM DB2, consulte a página de Drivers do Banco de Dados.
-
Essa série vídeo de dez minutos mostra o desenvolvimento em tempo real de uma pessoa trabalhando em um aplicativo da Web baseado no Ruby.
-
A Wikipedia tem uma excelente entrada sobre o paradigma de arquitetura do MVC.
- Encontre mais recursos para desenvolvedores Linux na developerWorks.
- Envolva-se com a comunidade do developerWorks participando de
blogs do developerWorks.
- Navegue em Manuais nesses e em outros tópicos técnicos.
- Inove seu próximo projeto de desenvolvimento Linux com o Software de período experimental IBM, disponível para download diretamente do developerWorks.
Para David Mertz, o mundo todo é um teste; ele devota sua carreira a fornecer instruções de testes marginais. Para saber mais sobre sua carreira, consulte sua página pessoal na Web. Ele escreve as colunas Charming Python e XML Matters do developerWorks desde 2000. Consulte seu livro, Text Processing in Python. É possível entrar em contato com David em mertz@gnosis.cx.