2. Reinaldo Junior
• UFES (since 2004)
• Desenvolvimento Web
• phpBB
• Eventos, comunidade, panelinha
sábado, 1 de outubro de 11
3. Plano de Vôo
• Framework
• Filosofia
• Ruby
• Rails
sábado, 1 de outubro de 11
4. Rails é um Framework
• “Abstração” (a resposta padrão de qualquer
pergunta na computação)
• REUSO
sábado, 1 de outubro de 11
5. Frameworks
• Frameworks = (components + patterns)
Ralph E. Johnson, 1997 (GoF)
• Contexto
• Específico de um Domínio
sábado, 1 de outubro de 11
6. WIN
• Vocabulário compartilhado
• Restrições inteligentes
• Foco na aplicação (e não no COMO)
sábado, 1 de outubro de 11
7. RUBY on Rails
• Ruby é a linguagem puts "maiusculo".upcase
• Foco no programador puts -5.abs
• Sintaxe elegante e natural 5.times do
puts "Ruby é Massa!"
• Extensibilidade end
sábado, 1 de outubro de 11
8. O.o
class Pato
def quack
"Quack!"
end • Tudo é um objeto
end
• Classes (begin ... end)
# Donald Duck
donald = Pato.new • Métodos (def ... end)
donald.quack
#retorna "Quack!"
sábado, 1 de outubro de 11
9. _Oooo_
class Pato puts Pato.new(2)
@@asas = 2 # Retorna "Asas: 2/2"
def initialize(asas=nil) puts Pato.new
@asas = [asas.to_i, @@asas].min # Retorna "Asas: 0/2"
end
puts Pato.new(10)
def to_s # Retorna "Asas: 2/2"
"Asas: #{@asas}/#{@@asas}"
end puts Pato.new.quack
end # Retorna "Quack!"
sábado, 1 de outubro de 11
10. Mixin
class Pato
module Mortal include Mortal
def machucado? end
@asas < @@asas
end class Ganso < Pato
# Err...
def morto? end
@asas.to_i.zero?
end class Ganso
include Mortal
def machuca
@asas = @asas - 1 unless morto? def quack
end "Ãhhn, Âhhn!"
end end
end
sábado, 1 de outubro de 11
11. Duck-typing
def faz_quack_quack(patos)
patos.each do |pato|
if pato.respond_to? :quack
puts pato.quack
end
end
end
coisas = [Pato.new, Ganso.new, Pessoa.new]
faz_quack_quack(coisas)
sábado, 1 de outubro de 11
12. Blocos
people.each do |person|
puts "* #{person.name}"
end
def em_par
yield
5.times {
yield
puts "Ruby rocks!"
end
}
em_par {
[2,1,3].sort! { |a, b|
"Tentativa #{i}"
b <=> a
}
}
(0..10).each{ |i| puts i }
sábado, 1 de outubro de 11
14. Ruby Way
def caminho(options={})
default = {
:origem => 'Vitória', :destino => 'Vila Velha'
}
opt = default.merge(options)
"#{opt[:origem]} --> #{opt[:destino]}"
end
caminho()
caminho(:origem => 'Campos')
caminho(:destino => 'São Paulo')
caminho :destino => 'Macaé', :origem => 'Manaus'
sábado, 1 de outubro de 11
15. Ruby on Rails
• DRY - Don’t Repeat Yourself
• COC - Convention Over Configuration
• Preguiça Virtuosa (aka Automatização)
• MVC, REST
• Comunidade
sábado, 1 de outubro de 11
16. Instalando
• Windows
• http://railsinstaller.org/
• Linux
• apt-get install ruby irb rubygems
• gem update --system
• gem install rails
• Mac (já vem instalado)
sábado, 1 de outubro de 11
17. Criando uma Aplicação
~ $ rails new dummy
[...]
• Estrutura de ~ $ cd dummy
arquivos definida
~/dummy $
~/dummy $ ls
Gemfile app db log test
README config doc public tmp
Rakefile config.ru lib script vendor
sábado, 1 de outubro de 11
18. Iniciando a App
~/dummy $ rails server
Could not find gem 'sqlite3 (>= 0) ruby' in any of the
gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.
~/dummy $ bundle install
Fetching source index for http://rubygems.org/
[...]
Your bundle is complete! Use `bundle show [gemname]`
to see where a bundled gem is installed.
sábado, 1 de outubro de 11
19. Executando o Web
Server
~/dummy $ rails server
=> Booting WEBrick
=> Rails 3.0.10 application starting in development on
http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
~/dummy $ rails server -d
~/dummy $ tail -f log/development.log
sábado, 1 de outubro de 11
23. “Teste Unitário”
~/dummy $ rails console
Loading development environment (Rails 3.0.10)
:001 > Post
=> Post(Table doesn't exist)
:002 > Post.all
ActiveRecord::StatementInvalid: SQLite3::SQLException:
no such table: posts: SELECT "posts".* FROM "posts"
from [...]
sábado, 1 de outubro de 11
24. Mais preguiça
~/dummy $ rake db:create
[...]
~/dummy $ rake db:migrate
== CreatePosts: migrating ==========================
-- create_table(:posts)
-> 0.0019s
== CreatePosts: migrated (0.0020s) =================
sábado, 1 de outubro de 11
30. Model
• Mantém o estado da aplicação (persistente ou
não)
• Regras de negócio que se aplicam ao estado
sábado, 1 de outubro de 11
31. ActiveRecord = ORM
• OO <=> DB relacional
• tabelas <=> classes
• registros <=> objetos
• colunas <=> propriedades
• Tudo isso SEM SQL
• 90% da sua aplicação
sábado, 1 de outubro de 11
32. Migrations
# db/migrate/20110930150650_create_posts.rb
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.string :title
t.text :body
t.decimal :rating
t.integer :viewed
t.timestamps # created_at e updated_at
end
end
def self.down
drop_table :posts
end
end
sábado, 1 de outubro de 11
33. posts
title body viewed
• Tabela no plural
Rock And
Bla bla bla... 3
Rails
• Classe no singular
Inscrições
abertas
Etc e tal 2
• app/models/<classe>.rb
# app/models/post.rb
class Post < ActiveRecord::Base
# Sim, só isso
end
novo = Post.new :title => 'O evento começou'
post = Post.find(3)
Post.destroy(2)
sábado, 1 de outubro de 11
34. novo = Post.new(
:title => 'O evento começou',
:body => '...'
)
novo.save
post = Post.find(3)
post[:title]
post.viewed
post.body = 'Atualizações'
post.save
Post.all
Post.find_by_title('Rock and Rails')
Post.find_all_viewed(3)
Post.where('viewed >= ?', 50).order('title ASC')
sábado, 1 de outubro de 11
35. Validação
• LT do Uriel (guenta aí)
sábado, 1 de outubro de 11
36. Associações
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
class User < ActiveRecord::Base
has_many :comments # fui eu
end
~/dummy $ rails generate scaffold User name:string
email:string
~/dummy $ rails generate scaffold Comment body:text
viewed:integer user:references post:references
sábado, 1 de outubro de 11
37. ~/dummy $ rake db:migrate
comentario = Comment.first
comentario.post # objeto
comentario.user_id # id
meus_comentarios = Comment.find_all_by_user_id(3)
eu = User.find_by_name('Reinaldo')
eu.comments # [objeto, objeto, ...]
eu.comment_ids # [id, id, ...]
eu.comments.find(3)
eu.comments.where('viewed >=', 50)
sábado, 1 de outubro de 11
38. eu = User.find_by_name('Reinaldo')
novo = eu.comments.create(:body => 'Massa!')
popular = eu.comments.order('viewed DESC').limit(1)
outro = Comment.new(:body => 'Rox!')
outro.user = User.find_or_create_by_name_and_email(
'M3nd3s', 'm3nd3s@gmail.com'
)
outro.save
sábado, 1 de outubro de 11
39. Many-to-Many
~/dummy $ rails generate model
Authorship post:references
user:references order:integer
class Post < ActiveRecord::Base
has_many :comments
has_many :authorships
has_many :users, :through => :authorships
end
class Authorship < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
sábado, 1 de outubro de 11
40. post = Post.new(
:title => 'Give me Fuel!'
)
post.users << User.first
post.save
post.authorships
post.authorships << Authorship.create(
:user => User.find(3),
:order => 1
)
sábado, 1 de outubro de 11
41. class Post < ActiveRecord::Base
post = Post.first
has_many :comments
reinaldo = User.first
has_many :authorships
has_many :authors, post.authors << reinaldo
:through => :authorships, post.authorships
:source => :user
comment = Comment.new(
has_many :commenters, :body => 'Yeah',
:through => :comments, :user => User.find(2)
:source => :user
)
end
post.comments << comment
post.save
class User < ActiveRecord::Base
has_many :comments post.reload
has_many :authorships reinaldo.reload
has_many :posts,
:through => :authorships post.commenters
end reinaldo.posts
sábado, 1 de outubro de 11
42. Rotas
• Avaliam as requisições e encaminham para
um Controller + Action
• Criam métodos (helpers) que geram URLs
• Requisição HTTP: caminho (URI) e método
HTTP (GET, POST, PUT, DELETE)
sábado, 1 de outubro de 11
43. Fluxo
• http://localhost:3000/say/hello
• Cliente => Servidor => Web Server
• Rota => Controller => Action => View
• Servidor => Cliente
sábado, 1 de outubro de 11
44. Configurando as rotas
# config/routes.rb
Dummy::Application.routes.draw do
# Suas rotas aqui
get '/say/hello/',
:controller => 'say',
:action => 'hello'
get '/say/goodbye' => 'say#goodbye'
post '/say/hey-ya' => 'say#hello'
end
sábado, 1 de outubro de 11
45. ~/dummy $ rake routes
say_hello GET /say/hello(.:format)
{:controller=>"say", :action=>"hello"}
say_goodbye GET /say/goodbye(.:format)
{:controller=>"say", :action=>"goodbye"}
POST /say/hey-ya(.:format)
{:controller=>"say", :action=>"hello"}
sábado, 1 de outubro de 11
46. Métodos
say_hello_path()
say_hello_url()
say_goodbye_path
say_goodbye_url
link_to("Diz olá pra mim!", say_hello_path())
link_to "Tchau!", say_goodbye_url
sábado, 1 de outubro de 11
47. REST
• REST (Representational State Trasfer)
• Roy Fielding (Tese de Ph.D. ), cara do HTTP
• Princípios
• Protocolo sem estado
• Recursos, identificados universalmente (URI)
• Operações bem definidas que se aplicam a todos
os recursos
• Múltiplas representações do mesmo recurso
sábado, 1 de outubro de 11
48. Recursos
Método Path Action
GET /posts index
GET /posts/new new
resources :posts
POST /posts create
resources :comments
GET /posts/:id show
resources :users
GET /posts/:id/new edit
PUT /posts/:id update
DELETE /posts/:id destroy
link_to("Listar posts", posts_path())
link_to "Veja os posts", posts_path
link_to "Leia esse post", show_post_url(@post)
link_to "Leia esse post", @post
sábado, 1 de outubro de 11
49. Controllers
• Subclasse de ActionController::Base
• Convenção
• app/controllers/<nome>_controller.rb
• class <Nome>Controller
• Se for um controller de recursos, nome é
no plural
sábado, 1 de outubro de 11
50. Actions
• Métodos do públicos do Controller
• Renderiza Views para gerar a resposta
• Disponibiliza variáveis de instância pra View
• Acesso aos parâmetros pelo hash “params”
• Convenção
• renderiza uma view com o mesmo nome
sábado, 1 de outubro de 11
51. # app/controllers/say_controller.rb
class SayController < ApplicationController
before_filter :get_time
def hello
@message = params[:message] || 'Olá amigo!'
end
def goodbye
@message = params[:message] || 'Até mais, colega!'
end
protected
def get_time
@time = Time.now
end
end
sábado, 1 de outubro de 11
52. Feels like ASP/PHP
<!-- app/views/say/hello.html.erb -->
<p>
<strong><%= @message %></strong><br />
Você chegou às <em><%= @time %></em>.
</p>
<!-- app/views/say/goodbye.html.erb -->
<p>
<strong><%= @message %></strong><br />
Você está saindo às <em><%= @time %></em>.
</p>
sábado, 1 de outubro de 11
53. redirect_to, render
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
# POST /posts
def create
@post = Post.new(params[:post])
if @post.save
redirect_to(@post, :notice => 'Post criado com sucesso.')
else
render :action => "new"
end
end
end
sábado, 1 de outubro de 11
54. Views
• Handlers
• ERB, RJS, Builder, RHTML, RXML
• Formats
• html, xml, json, js
• Convenção
• app/views/<controller>/
• <view>.<formato>.<handler>
sábado, 1 de outubro de 11
55. Rendering
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
end
end
sábado, 1 de outubro de 11
56. <!-- app/views/posts/index.html.erb -->
<h1>Nossos Posts</h1>
<% @posts.each do |post| %>
<h2><%= post.title %></h2>
<div class="rating"><%= post.rating %></div>
<%= link_to 'Leia na íntegra', post %>
<% end %>
sábado, 1 de outubro de 11
57. Partials
<!-- app/views/posts/index.html.erb -->
<h1>Post em nosso site</h1>
<%= render @posts %>
<!-- app/views/posts/_post.html.erb -->
<h2><%= post.title %></h2>
<div class="rating"><%= post.rating %></div>
<%= link_to 'Leia na íntegra', post %>
sábado, 1 de outubro de 11
59. Form Helpers
<%= form_for(@post) do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
sábado, 1 de outubro de 11
60. ActiveSupport
1.ordinalize # 1st
100.ordinalize # 100th
1.gigabyte / 512.kilobytes
# 2048
1.month.from_now
"author_id".humanize 3.days.ago
# Author id 10.minutes.from_now
"post".pluralize Time.now + 2.hours
# posts
date.at_beginning_of_week
"primeiro evento".titleize
# Primeiro Evento
sábado, 1 de outubro de 11
61. Perguntas?
• Rails Escala?
Saying “Rails doesn’t scale” is like saying “my car doesn’t go
infinitely fast”
- Pushion Passenger Team
• Posso usar XYZ com Rails? SIM
• Rails é melhor que XYZ? SIM e NÃO
• Rails é bom apenas pra CRUD? NÃO e SIM
• Qual o salário de programador Rails? ...
• Como faço XYZ com Rails? Google!
sábado, 1 de outubro de 11
63. Créditos das Imagens
• http://vvn.net/wp/2008/09/18/ruby-on-rails-
architecture/
• Agile Web Development With Rails, 3rd Ed.
• yUML.me
sábado, 1 de outubro de 11