Maurício Linhares Desenvolvedor Java Ruby C# JUGLeader do PBJUG
Completamente, absurdamente,
absolutamente, plagiadamente, baseado em...
Programming Ruby – The Pragmatic
Programmers Guide 2nd. Por Dave Thomas, A d H t Ch d F l
Andy Hunt e Chad Fowler;
Agile Web Development with Rails 2nd. Dave
Do Japão
Yukihiko “Matz” Matsumoto
Trazida ao mundo ocidental pelos Pragmatic
Programmers
Andy Hunt e Dave Thomas (livro da machadinha)
Completamente orientada a objetosp j
Linguagem “de script” interpretada;
Muito influenciada por Smalltalk e Perl;
Contém conceitos de linguagens funcionais
(closures – blocos de código);
( g );
Completamente dinâmica (tudo pode mudar Completamente dinâmica (tudo pode mudar
IRB é o “Interactive Ruby”, o console da
linguagem;
Pode-se enviar comandos ou se definir
classes, módulos, funções e qualquer outra coisa pra se utilizar durante uma sessão;
numero = 30
outro_numero = -20
numero + outro_numero
Não se usam ‘;’ ou qualquer outra coisa pra
indicar o fim de uma linha, o fim da linha é o fi d li h
fim da linha, oras;
Variáveis não tem tipo, elas simplesmente
guardam um objeto qualquer, de qualquer ti
tipo;
Quando nós vamos dar nomes a variáveis,
normalmente separamos nomes compostos “ ”
Eu faço “quack()”, “nadar()” e “voar()”, nadar() e voar() , igual a qualquer outro pato, eu sou ou não um
p ,
ê
Pois é, você perdeu a aula de Smalltalk né?
Não importa qual o tipo do objeto, o que
importa são as mensagens (métodos?) que ele é capaz de responder;
Se faz quack, nada e voa feito um pato,
def soma( primeiro, segundo) primeiro + segundo
end
soma( 10, 20)
A definição de um método começa com “def”
depois vem o nome do método e depois seus
â t t t
parâmetros entre parenteses;
Blocos de código, como métodos, classes,
“ifs” são sempre fechados com “end”, aqui ã t “{}” ã
E R b ã “ ” úl i
Em Ruby não se usa “return”, se a última
expressão no corpo de um método for avaliada para um valor esse valor é avaliada para um valor, esse valor é
retornado (Lembra do “Effective Java”? Não? Pois deveria!);)
O uso de parênteses não é obrigatório na p g
chamada de métodos, mas tenha cuidado com a legibilidade;
Bem, você ainda pode usar “return” se
quiser mas é feio oras; quiser, mas é feio, oras;
l S
class Song
def initialize(name, artist, duration) @name = name @artist = artist d d @duration = duration end end
musica = Song.new “Denied”, “Sonic Syndicate”, 3
i i t
A definição de uma classe começa com a
palavra “class”;
As classes são sempre “abertas”, você pode
redefinir os métodos de uma classe em
qualquer lugar, é só declarar ela outra vez;
Nomes de classe normalmente são definidos
usando CamelCase (como em NomeDeClasse);
Os contrutores são os métodos “initialize()”,
que são invocados indiretamente, através do
ét d d l “ ”
método de classe “new”;
Não é possível fazer sobrecarga de
construtores em Ruby =( ;
Variáveis de instância tem o nome começado
class Song
attr_writer :duration attr_reader :duration attr_acessor :title_
end
song = Song new("Bicylops" "Fleck" 260) song Song.new( Bicylops , Fleck , 260) song.duration = 257
song title = ‘Triciclops’ song.title = Triciclops
attr_reader define métodos de acesso a um
atributo de instância de um objeto;
attr_writer define métodos de alteraçao a
um atributo de instância de um objeto, assim como o reader, ele cria a variável dentro do
bj t objeto;
attr_acessor faz o mesmo que os dois
class Song
def duration_in_minutes @duration/60.0
end
def duration_in_minutes=(new_duration) @duration = (new duration * 60) to i @duration (new_duration 60).to_i
end end end
Criamos métodos de acesso a um atributo,
mas o cliente não sabe se são métodos ou se
l tá d t ib t di t t
ele está acessando os atributos diretamente;
Sobrescrevemos o operador “=“ (atribuição)
para a nossa propriedade, Ruby tem
b d d ( l )!
l S Li class SongList @@calls_total MAX TIME 5*60 # 5 i MAX_TIME = 5*60 # 5 minutos MIN_TIME = 1*60 # 1 minuto d f S l def SongList.is_too_long(song) song.duration > MAX_TIME end
def self.is_too_short(song)
song.duration < MIN_TIME
end end
Variáveis de classe são definidas com dois
“@”, como em “@@variavel_de_classe”;
Constantes são definidas com o seu nome
completo em “caixa alta” (na verdade é só a primeira letra, mas use o NOME COMPLETO);
Métodos de classe são definidos colocando o
nome da classe antes do nome do método ou usando “self” (é o “this” em Ruby);
l M Cl
class MyClass
def method1 # o padrão é public
end end protected def method2 end private d f th d3 def method3 end public public def method4 end end
Os níveis de acesso são definidos em blocos,
quando não há definição, é public, quando se d fi i í l d d
quer definir um nível de acesso, deve-se utilizar um bloco de acesso;
a = [ 3.14159, "pie", 99 ] a[0] # 3.14159
a[3] # nil
a << 123 # adicionando um item
a[4] = 456 #adicionando outro item
a[-1] # 456 – acessando de trás pra frente a[ 1] # 456 acessando de trás pra frente a[2..4] # [99, 123, 456]
Arrays são definidos pela simples declaração
de “[]”, como em “a = []”, também pode-se
f “ A ”
fazer “a = Array.new”;
Arrays são acessados pelo índice, tanto
positivo (ordem crescente) como negativo
( d d t )
(ordem decrescente);
Quando se acessa um índice que não existe
Novos items podem ser colocados no array
simplesmente utilizando o próprio operador
“[]” “ [10] 10”
“[]”, como em “a[10] = 10”;
Para se adicionar um item no fim do array
usa-se o operador “<<“, como em “a << 10”;
Arrays podem ser pegos em ‘pedaços’ como
em “a[1..3]”, que cria um novo array com os itens do índice 1 ao 3;
h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } h.length # 3 h['dog'] # "canine" h['cow'] = 'bovine' h[12] = 'dodecine'[ ] h['cat'] = 99
São conjuntos de “chave-valor” (Lembra do
Map em Java?);
São declarados com o uso de “{}” como em
“h = {}”, ou usando Hash.new;
Para se adicionar itens basta usar o operador
class SongList
def with_title(title)
for i in 0...@songs.length
return @songs[i] if title == g [ ] @songs[i].name end return nil end end end
class SongList
def with_title(title)
@songs.find {|song| title == song.name }
end end
Blocos são pedaços de código que podem ser
passados como parâmetros para funções,
f l t b lh i l
para fazer algum trabalho especial, como filtragem, ordenação e outros;
Você pode definir os seus próprios métodos
it bl
def fib_up_to(max)
i1, i2 = 1, 1 # atribuição paralela (i1 = 1 and i2 = 1)
while i1 <= max
yield i1
i1, i2 = i2, i1+i2, ,
end end end
fib up to(1000) {|f| print f " " } fib_up_to(1000) {|f| print f, }
O método não tem nada de especial, a sua
definição fica igual a qualquer outro método
l d ã b â t
e ele pode ou não receber parâmetros;
Na implementação do método, você invoca o
método especial “yield” para executar o
bl bl b â t ê
bloco, se o bloco recebe parâmetros, você os passa para o método “yield”;
'escape using "\\"' # escape using "\"
'That\'s right' ! #That's right
"Seconds/day: #{24*60*60}" # Seconds/day: 86400
def to_s
“Song: #@song Artist: #{@artist}”Song: #@song Artist: #{@artist} end
#Q!String de muitas linhas com aspas duplas e acessando variáveis #{variavel}!
#q( String de muitas linhas com aspas simples, aqui não pode ter variável )
ê
Strings são sequências de caracteres de 8
bits, não necessariamente Unicode;
Elas podem ser definidas usando ‘’ (aspas
simples) ou “” (aspas duplas);
Usando aspas duplas você pode colocar
expressões ou variáveis com o uso do
caracter “#” seguido de “{}” para variáveis de método ou funções ou apenas ‘@’ para
á d â
1 10 # [1 2 3 4 5 6 7 8 9 10] 1..10 # [1,2,3,4,5,6,7,8,9,10] ' ' ' ‘ # l b d lf b ? 'a'..'z‘ # lembra do alfabeto?
[ 2 3 ] my_array = [ 1, 2, 3 ]
0...my_array.length # [0,1,2,3,4]
(1..10).to_a # [1, 2, 3, 4, 5, 6, 7, 8, 9,10] ('bar'..'bat').to_a # ["bar", "bas", "bat"]
ê
São um conjunto de objetos em sequência,
normalmente caracteres ou números;
São definidos através da declaração de [
‘valor inicial’ .. ‘valor final’ ], como em [1..100];
Você pode definir os seus próprios ranges
class VU include Comparable
class VU include Comparable attr :volume def initialize(volume) @ l l @volume = volume end def to_s l '#' * @volume end def <=>(other) self.volume <=> other.volume end def succ
raise(IndexError, "Volume too big") if @volume >= 9 VU.new(@volume.succ)
end end
num = 81 6.times do
puts "#{num.class}: #{num}" num *= num
d f l d d ( 1 "Mil " 2 "C l "
def cool_dude(arg1="Miles", arg2="Coltrane", arg3="Roach")
"#{arg1} #{arg2} #{arg3} "#{arg1}, #{arg2}, #{arg3}.
end
cool_dude # "Miles, Coltrane, Roach."
cool dude("Bart") # "Bart Coltrane Roach " cool_dude( Bart ) # Bart, Coltrane, Roach. cool_dude("Bart", "Elwood") # "Bart, Elwood,
Roach " Roach.
cool_dude("Bart", "Elwood", "Linus") # "Bart, Elwood, Linus."
def meth_three
100.times do |num| square = num*num
return num, square , q if square > 1000q
end end end
meth three # [32 1024] meth_three # [32, 1024]
def five(a, b, c, d, e)
"I was passed #{a} #{b} #{c} #{d} #{e}"
end
five(1, 2, 3, 4, 5 ) # "I was passed 1 2 3 4 5"
five(1 2 3 *['a' 'b']) # "I was passed 1 2 3 a b" five(1, 2, 3, [ a , b ]) # I was passed 1 2 3 a b five(*(10..14).to_a) # "I was passed 10 11 12 13
14" 14
class SongList
def create_search(name, params) # ...
end end
list.create_search('short jazz songs', :genre => :jazz
:genre => :jazz,
" #{ }" if d b puts "a = #{a}" if debug
i l l l ?
print total unless total.zero?
f 2
if x == 2 puts x
elsif x < 0
puts “#{x} é menor que zero”
else
puts ‘Caiu no else’
leap = case
when year % 400 == 0: true
when year % 100 == 0: false
else year % 4 == 0y
i li case input_line when "debug" d d b i f dump_debug_info dump_symbols h when /p\s+(\w+)/ dump_variable($1)
when "quit", "exit"
exit else
print "Illegal command: #{input_line}"
print "Hello\n" while false
begin
print "Goodbye\n"
p y
end while false
while x < 10 puts “X é #{x}” puts X é #{x} x = x + 1 d end
3.times do print "Ho! “ end 0.upto(9) do |x| print x " " print x, end
for i in ['fee', 'fi', 'fo', 'fum'] print i, " " end for i in 1..3 print i " " print i, end
while line = gets
next if line =~ /^\s*#/ # pular comentários break if line =~ /^END/ # parar no fim
# executar coisas
redo if line.gsub!(/`(.*?)`/) { eval($1) } # process line
# process line ... end
for i in 1..100
print "Now at #{i}. Restart? "
retry if gets =~ /^y/i
Admita, você já estava cansado de tanto mexer e não ver nada né?
Um framework web completo, baseado no
MVC “web” (lembra disso?);
Ele define aonde cada pedaço de código deve
ficar e como ele deve ser acessado;
Convenções são melhor do que a liberdade
Né pra repetir
ó
código não,
rapá!
Projeto “Depot” do livro “Agile Web
Development With Ruby”;
Aplicação de vendas de produtos a clientes;
Uma interfaces para clientes, outra para a p , p
README Documentação
Rakefile Arquivo de build Rakefile Arquivo de build
components/ Esqueça =P
doc/ Mais documentação
lib/ Código genérico da aplicação
script/ Scripts de build
d / Pl i li ã
vendor/ Plugins para a sua aplicação
app/ Código da sua aplicação!
db/ Migrations e geração de banco db/ Migrations e geração de banco
log/ Arquivos de log
test/ Testes da sua aplicação
config/ Configuração geral
tmp/ Arquivos temporários do Rails public/ Arquivos estáticos (html, js, css)
development: adapter: mysql database: depot_development username: root password: host: localhost host: localhost
class CreateProducts ActiveRecord::Migration
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|_ p | | t.column :title, :string
t.column :description, :text t l i g l t i g t.column :image_url, :string
t.column :price, :decimal, :precision => 8, :scale => 2, :default => 0
end
end
def self down
def self.down
drop_table :products
end end
O b d d d l d
O seu banco de dados com controle de
versão!
Define tabelas, adiciona linhas, cria índices e
ainda faz a janta! ainda faz a janta!
Contém métodos utilitários para criar alterar Contém métodos utilitários para criar, alterar
e remover tabelas, colunas e linhas;
Você faz no “up” e desfaz no “down”, não se
ll i di d ll ã (
:null – indica se pode ser null ou não
(true-false)
:limit – indica o tamanho máximo do campo :default – indica o valor padrão do campo :precision – indica a precisão do número
:scale – indica a escala do número (quantas
casas depois da vírgula) casas depois da vírgula)
create_table :authors_books, :id => false do
|t|
t.column :author_id, :integer, :null => false
t.column :book_id, :integer, :null => false end
class CreateLineItems < ActiveRecord::Migration
def self.up
execute "alter table line_items
add constraint fk_line_item_products foreign key (product_id) references
products(id)“
end
def self.down
drop_table :line_items
end end
ruby script/generate scaffold product admin
def index
def index list
render :action => 'list'
end
def list
@ d t g @ d t gi t d t @product_pages, @products = paginate :products, :per_page => 10 end def show @product = Product.find(params[:id]) end end def new @product = Product.new end
def create
def create
@product = Product.new(params[:product])
if @product.savep
flash[:notice] = 'Product was successfully created.'
redirect to :action => 'list' redirect_to :action => list
else
render :action => 'new'
end end
def edit
@product = Product.find(params[:id])
d f d t
def update
@product = Product.find(params[:id])
if @product update attributes(
if @product.update_attributes( params[:product])
flash[:notice] = 'Product was flash[:notice] Product was successfully updated.'
redirect_to :action => 'show' , :id => @product
else
d ti ' dit' render :action => 'edit'
end end end
rake db:migrate #rodando o migration
ruby script/server webrick #iniciando o servidor
Todo mundo vem de ApplicationController;
As URLs nomalmente são
.../’nomeDoController’/’metodoDoController ’/’aqui pode vir um id ou não’, como em
“/admin/edit/10”;
Todos os métodos públicos de um controller
podem se chamados, métodos não públicos não ficam disponíveis (segurança rapá!);
ti d ti tá action_name – nome da action que está
executando;
headers – hash com os cabeçalhos HTTP (você pode colocar novos se quiser);
p q );
params – parametros que vieram da requisição, í
podem ser acessados usando símbolos ou strings; fl h bj t d d
flash – objeto que pode guardar uma mensagem entre uma requisição e outra (como enviar uma mensagem pra um redirect);g p );
domain – retorna o domínio que veio na
requisição
remote_ip – retorna o ip que gerou a
requisição;
env – hash de parametros enviados pelo
browser (como língua);
method – retorna o método http invocado
como um símbolo, :get, :post e ect;
get?, post?, put?, delete?, xml_http_request?,
É ê
É um hash de strings, onde você pode passar
qualquer valor;
Você só pode passar Strings;
Sempre use o atributo “cookies” para enviar p p
cookies para o navegador, nunca envie usando o atributo “headers”;
R ã HTTP d á i
Representa uma sessão HTTP de um usuário
com a aplicação;
Você pode colocar valores dentro dela, como
se ela fosse um hash; se ela fosse um hash;
Os valores podem ser qualquer coisa Os valores podem ser qualquer coisa,
contanto que seja um objeto que possa ser serializado;;
rake db:sessions:create
rake db:migrate
config.action_controller.session_store = :active_record_store_ _
<% form_tag :action => 'update', :id => @product do %>
<%= render :partial => 'form' %> <%= submit_tag 'Editar' %>
<% end %>
<%= link_to 'Mostrar', :action => 'show', :id => @product %> |
@p |
f é f ã d j d
form_tag é uma função de ajuda que gera
um formulário através de um bloco de código;
código;
render :partial => ‘form’ vai “incluir” o render :partial => form , vai incluir o
arquivo “_form” dentro da página
submit_tag ‘Editar’ gera um botão clicável link_to ‘Editar’ :action => ‘show’ gera um
link para o método ‘show’ do controllerp atual;
<% error messages for 'product' %> <%= error_messages_for product %> <!--[form:product]-->
<p><label for="product_name">Nome</label><br/> % t t fi ld d t % /
<%= text_field :product, :name %></p>
<p><label for="product_category">Categoria</label><br/>
l d d lh
<%= select :product, :category_id, @categories, :prompt => "Escolha uma categoria"%> </p>
p label for "prod ct label" Marca /label br/ <p><label for= product_label >Marca</label><br/>
<%= select :product, :label_id, @labels, :prompt => "Escolha uma marca" %> </p>
<p><label for="product_price">Preço real</label><br/> <%= text_field :product, :real_price %></p>
<! [eoform:product] > <!--[eoform:product]-->
text_field e select são utilitários para gerar
um campo de entrada e um select HTML,
i t t tilitá i t d
existem outros utilitários para todos os outros componentes HTML;
O uso de símbolos, como em “text_field
d t ” é di d d
:product, :name” é para dizer de onde vem o campo e que campo é que nós queremos
mostrar (veja o código fonte gerado!); mostrar (veja o código fonte gerado!);
@categories = Category.find( :all, :order => :name).map { |c| [c.name, c.id] }
Ao mostrar alguma coisa em um select, ele deve vir em um array de arrays, onde o primeiro item é o “label” do select e o
d it é “ l ” d l t
% f f d t l { ti t } d <% form_for :product, :url => { :action => :create } do
|form| %>
<p>Title: <%= form.text_field :title, :size => 30 %></p> <p>Description: <%= form.text_area :description, :rows
=> 3 %></p>
<p>Price: <%= form.text_field :price, :size => 10 %></p>
<p><%= submit_tag %></p> % d %
É
É feito especificamente para gerar
formulários para objetos do modelo;
Os métodos utilitários de criação de
componentes são chamados direto no “form” e não é necessário repetir diversas vezes
l bj t l qual o objeto real;
class Product < ActiveRecord::Base class Product < ActiveRecord::Base
validates_presence_of :title, :description, :image_url validates_numericality_of :price
validates_uniqueness_of :title validates format of :image url, validates_format_of :image_url,
:with => %r{\.(gif|jpg|png)$}i,
:message => “deve ser um gif, jpg ou png" protected
def validate
errors.add(:price, “deve ser ao menos 0.01" ) if price.nil? || price < 0.01
end end
T d lid ã é d fi id d d ó i
Toda a validação é definida dentro do próprio
objeto do modelo;
Existem diversos métodos utilitários para
diversos tipos de validação; diversos tipos de validação;
Se nenhum dos métodos resolve o seu Se nenhum dos métodos resolve o seu
problema, implemente o método “validate”;
As mensagens aparecem em -> <%=
ruby script/generate migration add test data ruby script/generate migration add_test_data
class AddTestData < ActiveRecord::Migrationg
def self.up
Product.create(
titl 'P g ti V i C t l' :title => 'Pragmatic Version Control' ,
:description => %{<p>With Subversion</p>}, :image url => '/images/svn.jpg' ,g _ g jpg ,
:price => 28.50) end d f lf d def self.down Product.delete_all end end
<%= link_to ‘Remover',
{ :action => 'destroy', :id => product },
{ y , p },
:confirm => “Tem certeza?" , :method => :post %>
module ApplicationHelper
def format_price( price )
number_to_currency( price, :precision => 2, :unit => 'R$ ', :separator => ',', :delimiter => '.' )
end end
Cada controller tem o seu próprio helper e
existe um helper padrão que sempre está
di í l t d t ll
disponível para todos os controllers;
Todo o trabalho que possa ser de lógica das
views (como formatação, geração de
t l t t ) d f it l
templates e etc) deve ser feito por eles;
Ó
NAS VIEWS NÃO PODE HAVER LÓGICA,
% f f ( i t
<% form_for(:picture,
:url => {:action => 'save'},
:html > { :multipart > true }) do |form| :html => { :multipart => true }) do |form| %>
Comment: Comment:
<%= form.text_field("comment" ) %><br/> Upload your picture:
<%= form.file_field("uploaded_picture" ) %><br/>( p p ) <%= submit_tag("Upload file" ) %>
class Picture < ActiveRecord::Base
class Picture < ActiveRecord::Base
validates_format_of :content_type, :with => /^image/,
" l l d i t “ :message => "-- you can only upload pictures“
def uploaded_picture=(picture_field) lf b f f ld l f l self.name = base_part_of(picture_field.original_filename) self.content_type = picture_field.content_type.chomp self.data = picture_field.read end def base_part_of(file_name) File.basename(file_name).gsub(/[^\w._-]/, '' ) end end
def picture @picture = Picture.find(params[:id]) send_data(@picture.data, :filename => @picture.name,p , :type => @picture.content_type, :disposition => "inline" ) :disposition > inline ) end
Ei, você já está mexendo com ele desde o primeiro migration!
É
É a abstração de banco de dados de Rails;
Baseado no padrão de projeto “active
record”;
Cada coluna que você definiu lá no q
‘save’ e ‘save!’, salva ou atualiza um objeto,
‘save’ retorna true se conseguir salvar, false
ã bj t f i álid ‘ !’ l
senão ou o objeto for inválido, ‘save!’ lança uma exeção se não conseguir salvar ou se o objeto for inválido;
objeto for inválido;
‘d t ’ bj t d b d
‘destroy’ remove um objeto do banco de
dados e não deixa que nenhum dos seus atributos seja alterado;
update_attributes e update_attributes!,
recebem um hash com os parâmetros e
l d i d d d bj t t t
valores das propriedades do objeto e tentam enviar uma atualização para o banco de
dados; dados;
‘ t ’ i bj t h h d
‘create’ cria um novo objeto com o hash de
parametros passado e salva ele no banco de dados automaticamente;
Define um relacionamento de 1 pra N (como
em um item pertence a um produto, mas um
d t d t N it )
produto pode ter N itens);
Métodos adicionados:
product(reload = false) product=
build_product( hash ) create_product( hash )
D fi l d 1 d l i
Define o lado 1 do relacionamento um para
muitos;
Adiciona os métodos (e ainda outros...):
orders(force reload=false) orders(force_reload=false) orders <<order orders.push(order1, ...)orders.push(order1, ...) orders.replace(order1, ...) orders.delete(order1, ...) orders.destroy_all orders.size d ? orders.empty?
class Article < ActiveRecord::Base
has_and_belongs_to_many :users
end end
class User < ActiveRecord::Base
has and belongs to many :articles_ _ g _ _ y
Account.transaction do
account1.deposit(100)p ( ) account2.withdraw(100)
end end
name = params[:name] pos =
Order.find(:all,( ,
:conditions => "name = '#{name}' and pay_type = 'po'" )
name = params[:name] pos = Order.find(:all,
:conditions => ["name = ? and pay_type = 'po'" , name])
name = params[:name]
pay_type = params[:pay_type] pos =
Order.find(:all,( , :conditions =>
["name = :name and pay type = :pay type" [ name :name and pay_type :pay_type , {:pay_type => pay_type, :name => name}])
:order – para ordenar a consulta, use
símbolos;
:limit – quantidade máxima de itens que deve
ser trazida;
:offset – primeiro item a ser trazido;
:first – no lugar de :all, para trazer apenas
um item; u te ;
items = LineItem.find_by_sql("select *, " + " quantity*unit_price as total_price, " + " products.title as title " +
" from line_items, products " +_ , p
" where line_items.product_id = products.id " )
li = items[0]
puts "#{li.title}: #{li.quantity}x#{li.unit_price} > #{li total price}"
average = Order.average(:amount) max = Order.maximum(:amount) min = Order.minimum(:amount) total = Order.sum(:amount)( )
number = Order.count
#tudo isso pode receber :conditions, como o find
order = Order.find_by_name("Dave Thomas" )
orders = Order.find_all_by_name("Dave Thomas" )
order = Order.find_all_by_email(params['email' _ _ y_ (p [ ])
Obrigado pessoal! \o/