Este documento fornece instruções para instalação e configuração do framework Ruby on Rails, incluindo como instalar Ruby, RubyGems, Rails, PostgreSQL e bibliotecas, criar banco de dados e tabelas, gerar scaffolds, configurar servidor web e mais.
Multi-core Parallelization in Clojure - a Case Study
Ruby on Rails instalação
1. Ruby on Rails
Regis Pires Magalhães
regispiresmag@gmail.com
http://regispiresmag.googlepages.com
Última atualização em 24/01/2007
2. Instalação do Ruby
1 – No Linux - http://rubyforge.org/frs/download.php/7858/ruby-
1.8.4.tar.gz
tar xvzf ruby-<versão>.tgz
./configure
make
make install
2 – No Windows - One-Click Installer – já vem com RubyGems:
http://rubyforge.org/frs/download.php/11488/ruby184-20.exe
3. Instalação do RubyGems
• Desnecessário no Windows, pois já vem no One-Click Installer
• RubyGems - gerenciador de pacotes do Ruby
1 – Descompactar:
http://rubyforge.org/frs/download.php/11290/rubygems-0.9.0.zip
2 – Executar:
ruby setup.rb
4. Instalação do Rails
• Via Internet:
gem install rails --include-dependencies
• Local:
– Ir para diretório onde estão os arquivos gem e executar:
gem install activesupport actionpack actionmailer
activerecord actionwebservice rails –-local
– Arquivos necessários:
• rails-1.1.6.gem
• actionmailer-1.2.5.gem
• actionpack-1.12.5.gem
• actionwebservice-1.1.6.gem
• activerecord-1.14.4.gem
• activesupport-1.3.1.gem
5. Instalação do PostgreSQL
• No Windows:
– Descompactar:
• postgresql-8.1.4-1.zip
– Executar:
• postgresql-8.1.msi
6. Instalação da biblioteca do PostgreSQL para o
Ruby
• Via internet:
gem install postgres-pr
• Local:
gem install postgres-pr –-local
7. Criação do Banco de Dados
create database <projeto>_<ambiente>
create database livraria_development
Ambientes:
• Development - desenvolvimento
• Test - testes
• Production - produção
8. Criação de tabelas
• usuarios • tipos
– id serial (PK) – id serial (PK)
– nome varchar(75) – descricao varchar(50)
– email varchar(75)
– senha varchar(10)
• telefones
– – id serial (PK)
admin int4
– – usuario_id int4
img bytea
– numero varchar(10)
• categorias • produtos
– id serial (PK) – id serial (PK)
– descricao varchar(50) – descricao varchar(100)
– tipo_id int4
– categoria_id int4
9. Criação do Projeto
rails <projeto>
>rails livraria
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create components
create db
create doc
create lib
create lib/tasks
create log
...
10. Configuração do acesso
a banco de dados
• Abrir arquivo config/database.yml:
development:
adapter: postgresql
database: livraria_development
username: postgres
password: 1234
host: localhost
...
11. Testando o Servidor WEB
ruby script/server
ruby script/server –e [development|test|production]
• Development é o default.
12. Geração de um Scaffold
• Scaffold - tradução: andaime, palanque, armação , esqueleto
• Scaffold é um meio de criar código para um determinado modelo
através de um determinado controlador.
• É um meio de começarmos rapidamente a ver os resultados no
navegador Web e um método muito rápido de implementar o CRUD
(Create, Retrieve, Update, Delete) na sua aplicação.
ruby script/generate scaffold <Model> <Controller>
ruby script/generate scaffold Usuario Admin::Usuario
• O controlador Admin::Usuario gerenciará as ações recebidas. O rails irá
criar a seguinte estrutura de diretórios:
<aplicação>/controllers/admin
13. Outras gerações comuns
• Modelo:
ruby script/generate model <Model>
• Controlador:
ruby script/generate controller <controller>
14. Diretórios da aplicação
• controllers
– Classes de controle.
– Uma classe controller trata uma requisição Web do usuário.
– A URL da requisição Web é mapeada para uma classe de controle e
para um método dentro da classe.
• views
– Armazena as templates de visualização para preenchimento com
dados da aplicação, conversão para HTML e retorno para o browser.
• models
– Armazena as classes que modelam e encapsulam dos dados
armazenados nos bancos de dados da aplicação.
• helpers
– Armazena classes de auxílio usadas para ajudar as classes model,
view e controller. Ajudam a manter os códigos de model, view e
controller bastante enxutos.
15. Modelo
<aplicação>/app/models/usuario.rb:
class Usuario < ActiveRecord::Base
end
• A classe Usuario já é capaz de gerenciar os dados da tabela no
banco de dados.
• Não há necessidade de explicitar o mapeamento das colunas do
banco com atributos da classe.
• Rails não proíbe nada: se for necessário existe como mapear
uma coluna para outro atributo de nome diferente.
• Nome de tabela diferente da convenção:
class EncomendaCliente < ActiveRecord::Base
set_table_name quot;encomendas_clientesquot;
end
16. Modelo
• Toda entidade é criada no diretório padrão:
/app/models/<controller>/<model>.rb
• Toda entidade herda diretamente da classe
ActiveRecord::Base .
• Não há necessidade de mapear manualmente cada coluna
da tabela.
• Convenção: a classe tem o nome no singular (Usuario), a
tabela tem o nome do plural (usuarios).
• Convenção: Toda tabela tem uma chave primária chamada
id que é de tipo auto-incremento.
17. Active Record Interativo
ruby script/console
• Toda entidade criada pode ser manipulada
pelo console.
• Facilita testes antes de criar as actions.
18. Acrescentando validação
class Usuario < ActiveRecord::Base
validates_presence_of :nome
validates_length_of :nome,
:maximum => 75,
:message => quot;Máximo de %d caracteres.quot;
end
Outros exemplos:
validates_uniqueness_of :cpf
validates_length_of :cpf, :is => 11
validates_length_of :user_name, :within => 6..20,
:too_long => quot;deve ser menorquot;,
:too_short => quot;deve ser maiorquot;
validates_length_of :first_name, :maximum=>30
19. Controller
• Todo Controller fica no diretório:
/app/controllers/<nome>_controller.rb
• Todo Controller herda a classe ApplicationController
• Todo aplicativo Rails é criado com uma classe chamada
ApplicationController que herda de
,
ActionController::Base e é base de todos os outros
,
controllers
• Todo método de um controller é chamado de Action
• Uma classe Controller pode ter quantas Actions quanto
necessárias.
class Admin::UsuarioController < ApllicationController
def index
render :text => “Hello World!”
end
end
20. Acessando uma Action
• Roteamento Customizável (routes.rb)
http://localhost:3000/:controller/:action/:id
• Exemplo:
http://localhost:3000/blog/index
• blog = app/controller/blog_controller.rb
• index = método index em BlogController
22. Mais convenções
• Ao final de toda Action, Rails chamará uma view
com o mesmo nome da Action, no seguinte
diretório:
/app/views/<controller>/<action>.<ext>
• A extensão do arquivo pode ser:
– .rhtml - Embedded Ruby (HTML+Ruby)
– .rxml - XML Builder (Ruby puro)
– .rjs - Javascript Generator (Ruby puro)
• Este fluxo pode ser interrompido com uma
chamada explícita ao método render ou
redirect_to.
24. Layouts
• Layouts permitem o compartilhamento de conteúdo.
• Todo novo controller automaticamente ganha um
layout no diretório:
/app/views/layouts/<controller>.rhtml
• As views desse controller preenchem o espaço:
<%= @content_for_layout %>
25. Layouts
# test_controller.rb
class TestController < ApplicationController
layout quot;defaultquot;
def index
end
end
<!-- default.rhtml -->
<html>
<head>
<title>Teste</title>
</head>
<body>
<h1>Layout Padrao</h1>
<%= @content_for_layout %>
</body>
</html>
26. Scriptlets
<% @usuarios.each do |usuario| %>
Faz alguma coisa com usuario
<% end %>
...
<% if number == quot;7quot; %>
Está correto!
<% end %>
27. Flash
• flash[:notice] está disponível somente
naquela requisição. Usado para comunicação
entre ações: passagem de string contendo
informação ou erro.
• Similar a variáveis de sessão, mas somente
existe de uma página para outra. Uma vez
que a requisição para a qual foram
propagadas acaba, elas são
automaticamente removidas do contexto de
execução.
def three
flash[:notice] => quot;Helloquot;
flash[:warning] => quot;Mewlquot;
flash[:error] => quot;Erro!quot;
render
end
28. Logger
• Nível de log configurado em:
config/environment.rb:
config.log_level = :debug
• Mensagens escritas em um arquivo no
diretório log. O arquivo de log usado depende
do ambiente (environment) usado pela
aplicação. Ex.: log/development.log
logger.warn(quot;I don't think that's a good ideaquot; )
logger.info(quot;Dave's trying to do something badquot; )
logger.error(quot;Now he's gone and broken itquot; )
logger.fatal(quot;I give upquot; )
29. Paginação
• Para todas as ações do Controller:
class PersonController < ApplicationController
model :person
paginate :people, :order => 'last_name, first_name',
:per_page => 20
# ...
end
30. Paginação
• Para uma única ação do Controller:
def list
@person_pages, @people =
paginate :people, :order => 'last_name, first_name'
end
33. Paginação
• paginate(collection_id, options={}) – Retorna um paginator e
uma coleção de instâncias de modelo Active Record para a página
atual.
• Opções:
– :singular_name: the singular name to use, if it can‘t be inferred by singularizing the
collection name
– :class_name: the class name to use, if it can‘t be inferred by camelizing the singular
name
– :per_page: the maximum number of items to include in a single page. Defaults to 10
– :conditions: optional conditions passed to Model.find(:all, *params) and Model.count
– :order: optional order parameter passed to Model.find(:all, *params)
– :order_by: (deprecated, used :order) optional order parameter passed to
Model.find(:all, *params)
– :joins: optional joins parameter passed to Model.find(:all, *params) and Model.count
– :join: (deprecated, used :joins or :include) optional join parameter passed to
Model.find(:all, *params) and Model.count
– :include: optional eager loading parameter passed to Model.find(:all, *params) and
Model.count
– :select: :select parameter passed to Model.find(:all, *params)
– :count: parameter passed as :select option to Model.count(*params)
38. Associações
• Todo usuario pode ter vários telefones.
• Telefone pertence a Usuario através da coluna usuario_id.
• Convenção de Chave Estrangeira: <classe>_id
class Usuario < ActiveRecord::Base
has_many :telefones # um usuário tem muitos telefones
validates_presence_of :nome
validates_length_of :nome,
:maximum => 75,
:message => quot;Máximo de %d caracteres.quot;
end
class Telefone < ActiveRecord::Base
belongs_to :usuario # um telefone pertence a um usuário
end
43. Rake
• Programa em Ruby para realizar um
conjunto de tarefas (tasks).
• Cada tarefa tem um nome, uma lista de
tarefas das quais ela depende e uma lista
de ações a realizar.
• Para ver as tarefas existentes em um
arquivo rake (Rakefile):
rake --tasks
44. Testes Unitários
• Toda nova entidade ganha um arquivo para teste unitário em:
/app/test/unit/<entidade>_test.rb
• Devemos seguir os preceitos de Test-Driven Development:
“Se não vale a pena testar, para que estamos codificando?”
• Os testes acontecem em banco de dados separado do
desenvolvimento
<projeto>_test
• Cada teste roda de maneira isolada: os dados modificados em um teste
não afetam outro teste
• Cada teste unitário tem um arquivo de “fixture”, carga de dados para
testes:
/app/test/fixture/<tabela>.yml
• Executando todos os testes unitários
rake test:units
• Executando apenas um teste unitário:
ruby test/unit/<entidade>_test.rb
45. Testes Unitários
require File.dirname(__FILE__) + '/../test_helper'
class PostTest < Test::Unit::TestCase
fixtures :posts
# Replace this with your real tests.
def test_add_comment
# adiciona um post
@post = Post.create(:title => 'New Post',
:body => 'New Post',
:author => 'Anonymous')
# adiciona um comment
@comment = @post.comments.create(:body => 'New Comment',
:author => 'Anonymous')
assert_not_equal nil, @comment
# recarrega a entidade
@post.reload
# checa se existe apenas um post
assert_equal 3, Post.count # já existem 2 posts na fixture
# checa se esse post tem apenas um comment
assert_equal 1, @post.comments.count
end
end
46. Fixture YAML
• “YAML Ain’t a Markup Language”
• Maneira de serializar objetos Ruby em
forma de texto
• Formato humanamente legível
• Mais leve e simples que XML
47. Fixture YAML
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
ronaldo:
id: 1
name: Ronaldo
login: ronaldo
admin: true
email: ronaldo@reflectivesurface.com
data: 2004-07-01 00:00:00
hashed_password: <%= Digest::SHA1.hexdigest('abracadabra') %>
marcus:
id: 2
name: Marcus
login: marcus
admin: false
email: marcus@reflectivesurface.com
data: <%= 1.day.from_now.strftime(quot;%Y-%m-%dquot;) %>
hashed_password: <%= Digest::SHA1.hexdigest('teste') %>
53. Testes Funcionais
• Todo novo controller ganha uma classe de teste em:
/app/test/functional/<classe>_controller_test.rb
• Devemos testar cada action do controller
• Métodos como get e post simulam navegação com um
browser
• Executando todos os testes funcionais:
rake test:functionals
• Executando apenas um testes funcional:
ruby test/functional/<classe>_controller_test.rb
54. Testes Funcionais
require File.dirname(__FILE__) + '/../test_helper'
require 'blog_controller'
# Re-raise errors caught by the controller.
class BlogController; def rescue_action(e) raise e end; end
class BlogControllerTest < Test::Unit::TestCase
fixtures :posts
def setup
@controller = BlogController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_create
num_posts = Post.count # checa total de posts atual
# simula submit do formulário de criar novo post
post :create, :post => {:title => 'New Title', :body => 'New Post', :author => 'Anonymous'}
# checa se depois da action fomos redirecionados
assert_response :redirect
# checa se realmente foi acrescentado um novo post
assert_equal num_posts + 1, Post.count
end
end
55. Testes Funcionais
require File.dirname(__FILE__) + '/../test_helper'
require 'users_controller'
# Re-raise errors caught by the controller.
class UsersController; def rescue_action(e) raise e end; end
class UsersControllerTest < Test::Unit::TestCase
fixtures :users
def setup
@controller = UsersController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_index
get :index
assert_redirected_to :controller => quot;loginquot;, :action => quot;loginquot;
end
def test_index_with_login
@request.session[:user] = users(:ronaldo).id
get :index
assert_response :success
assert_tag :tag => quot;tablequot;, :children => { :count => User.count + 1,
:only => { :tag => quot;trquot; } }
assert_tag :tag => quot;tdquot;, :content => users(:ronaldo).name
end
end
61. Mais Testes
• Testes Unitários devem testar todos os aspectos da
entidade como associações, validações, callbacks,
etc
• Testes Funcionais devem testar todas as actions de
um mesmo controller, todos os fluxos,
redirecionamentos, filtros, etc
• Testes Integrados servem para avaliar a navegação
e fluxos entre actions de diferentes controllers.
Funcionam de maneira semelhante a um teste
funcional
62. Helpers
# Global helper para views.
module ApplicationHelper
# Formata um float com duas casa decimais
def fmt_decimal(valor, decimais)
sprintf(quot;%0.#{decimais}fquot; valor)
,
end
end
63. O que NÃO fizemos
• Não precisamos recompilar e reinstalar o aplicativo a cada
mudança.
• Não precisamos reiniciar o servidor a cada mudança.
• Não precisamos mapear cada uma das colunas das tabelas para
as entidades.
• Não precisamos configurar dezenas de arquivos XML.
Basicamente colocamos a senha do banco de dados, apenas.
• Não precisamos usar Javascript para fazer Ajax: a maior parte
pode ser feita com Ruby puro.
• Não sentimos falta de taglibs: expressões Ruby, partials foram
simples o suficiente.
• Não precisamos codificar código-cola, o framework possui
“padrões espertos” afinal, todo aplicativo Web tem a mesma
infraestrutura.
64. Referências
• Agile Web Development with Rails. 2ª Edição.
– Thomas e David Heinemeier Hansson.
• Entendendo Rails
– Fábio Akita (http://www.esnips.com/web/BalanceOnRails)
• Creating a weblog in 15 minutes
– http://media.rubyonrails.org/video/rails_take2_with_sound.mov
• Tutorial de Rails do TaQ
– http://www.eustaquiorangel.com/downloads/tutorialrails.pdf
• Tutorial de Ruby on Rails do Ronaldo Ferraz
– http://kb.reflectivesurface.com/br/tutoriais/rubyOnRails
• Rolling with Ruby on Rails by Curt Hibbs
– http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html
• Tutorial de Ruby do TaQ
– http://www.eustaquiorangel.com/downloads/tutorialruby.pdf