Apostila de Ruby do Maurício Linhares

Transcrição

Apostila de Ruby do Maurício Linhares
Maurício Linhares
€ 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 Hunt
H t e Chad
Ch d Fowler;
F l
Andy
€ Agile
Web Development with Rails 2nd. Dave
Thomas, David Heinemeier Hanson;
€ Do
ƒ
Japão
Yukihiko “Matz” Matsumoto
€ Trazida
ao mundo ocidental pelos Pragmatic
Programmers
ƒ
Andy Hunt e Dave Thomas (livro da machadinha)
€ Completamente
p
ƒ
orientada a objetos
j
Não existem tipos primitivos
€ Linguagem
€ Muito
“de script” interpretada;
influenciada por Smalltalk e Perl;
€ Contém
conceitos de linguagens funcionais
((closures – blocos de código);
g );
€ Completamente
dinâmica (tudo pode mudar
em tempo de execução);
€ 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
numero + outro_numero.abs
€ Não
se usam ‘;’ ou qualquer outra coisa pra
indicar o fim de uma linha, o fim da linha é o
fi da
fim
d linha,
li h 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
com “_”;
“ ”
Eu faço “quack()”,
“nadar()”
nadar() e “voar()”,
voar() ,
igual a qualquer outro
pato,, eu sou ou não um
p
pato?
€ 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,
então pra mim é um pato;
def soma( primeiro, segundo)
primeiro + segundo
end
soma( 10, 20)
soma 50, 90
€A
definição de um método começa com “def”
depois vem o nome do método e depois seus
parâmetros
â t
entre
t parenteses;
t
€ Blocos
de código, como métodos, classes,
“ifs” são sempre fechados com “end”, aqui
ã ttem “{}” não;
ã
não
€ Em
E
Ruby
R b não
ã se usa “
“return”,
” se a úl
última
i
expressão no corpo de um método for
avaliada para um valor,
valor esse valor é
retornado (Lembra do “Effective Java”? Não?
Pois deveria!);
)
€O
uso de p
parênteses não é obrigatório
na
g
chamada de métodos, mas tenha cuidado
com a legibilidade;
€ Bem,
você ainda pode usar “return” se
quiser mas é feio
quiser,
feio, oras;
class
l
S
Song
def initialize(name, artist, duration)
@name = name
@artist = artist
@duration
d
= duration
d
end
end
musica = Song.new “Denied”, “Sonic
Syndicate”, 3
musica.inspect
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
método
ét d d
de classe
l
“
“new”;
”
€ Não
é possível fazer sobrecarga de
construtores em Ruby =( ;
€ Variáveis
por “@”;
de instância tem o nome começado
class Song
attr_writer :duration
attr_reader :duration
_
:title
attr_acessor
end
Song new("Bicylops"
song = Song.new(
Bicylops , "Fleck"
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
anteriores juntos;
class Song
def duration_in_minutes
@duration/60.0
end
def duration_in_minutes=(new_duration)
(new duration * 60).to_i
60) to i
@duration = (new_duration
end
end
€ Criamos
métodos de acesso a um atributo,
mas o cliente não sabe se são métodos ou se
ele
l está
tá acessando
d os atributos
t ib t di
diretamente;
t
t
€ Sobrescrevemos
o operador “=“ (atribuição)
para a nossa propriedade, Ruby tem
b
d operadores
d
((alguns,
l
)!
sobrecarga
de
apenas)!
class
l
S
SongList
Li
@@calls_total
MAX TIME = 5*60 # 5 minutos
MAX_TIME
i
MIN_TIME = 1*60 # 1 minuto
d f SongList.is_too_long(song)
def
S
l
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);
class
l
MyClass
M
Cl
def method1 # o padrão é public
end
protected
def method2
end
private
d f method3
th d3
def
end
public
def method4
end
end
€ Os
níveis de acesso são definidos em blocos,
quando não há definição, é public, quando se
quer d
definir
fi i um nível
í ld
de acesso, d
deve-se
utilizar um bloco de acesso;
€ Um
bloco termina assim que outro se iniciar;
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]
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
fazer
“a
“ = Array.new”;
A
”
€ 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
em um array, ele retorna “nil”;
€ Novos
items podem ser colocados no array
simplesmente utilizando o próprio operador
“[]” como em “
“[]”,
“a[10]
[10] = 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
[], como em “h[‘chave’] = ‘valor’”;
class SongList
def with_title(title)
for i in [email protected]
g [ ] if title ==
return @songs[i]
@songs[i].name
end
return nil
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,
para fazer
f
algum
l
ttrabalho
b lh especial,
i l como
filtragem, ordenação e outros;
€ Você
pode definir os seus próprios métodos
it
bl
que aceitam
blocos;
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
fib up to(1000) {|f| print f,
fib_up_to(1000)
f ""}
€O
método não tem nada de especial, a sua
definição fica igual a qualquer outro método
e ele
l pode
d ou não
ã receber
b parâmetros;
â t
€ Na
implementação do método, você invoca o
método especial “yield” para executar o
bl
b parâmetros,
â t
ê os
bloco,
se o bl
bloco recebe
você
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}
#{@artist}”
“Song:
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 )
‘a’ << ‘b’ << ‘c’ # ‘abc’
€ 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
variáveis
á
d
de instância;
â
1 10 # [1
1..10
[1,2,3,4,5,6,7,8,9,10]
2 3 4 5 6 7 8 9 10]
' ' ' ‘ # lembra
'a'..'z‘
l b d
do alfabeto?
lf b ?
my_array = [ 1, 2,
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
com o operador “<=>” (disco voador?);
class VU include Comparable
attr :volume
def initialize(volume)
@ l
@volume
= volume
l
end
def to_s
'#' * @volume
l
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
end
deff cool_dude(arg1="Miles",
d
l d d ( 1 "Mil " arg2="Coltrane",
2 "C l
"
arg3="Roach")
#{arg1}, #{arg2}
#{arg2}, #{arg3}
#{arg3}."
"#{arg1}
end
cool_dude # "Miles, Coltrane, Roach."
cool dude("Bart")
Coltrane Roach
cool_dude(
Bart ) # "Bart
Bart, Coltrane,
Roach."
cool_dude("Bart", "Elwood") # "Bart, Elwood,
Roach "
Roach.
cool_dude("Bart", "Elwood", "Linus") # "Bart,
Elwood, Linus.
Linus."
def meth_three
100.times do |num|
square = num*num
q
if square
q
> 1000
return num,, square
end
end
meth three # [32
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
b"
five(1,
2, 3
3, *['a'
[ a , 'b'])
b ]) # "II 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,
:jazz
:duration_less_than => 270)
puts "a
" = #{
#{a}"
}" if debug
d b
print
i totall unless
l
total.zero?
l
?
iff x == 2
puts x
elsif x < 0
puts “#{x} é menor que zero”
else
puts ‘Caiu no else’
end
leap = case
when year % 400 == 0: true
when year % 100 == 0: false
else yyear % 4 == 0
end
case input_line
i
li
when "debug"
d
dump_debug_info
d b
i f
dump_symbols
when
h /p\s+(\w+)/
dump_variable($1)
when "quit", "exit"
exit
else
print "Illegal command: #{input_line}"
end
print "Hello\n" while false
begin
print "Goodbye\n"
p
y
end while false
while x < 10
puts “X
X é #{x}
#{x}”
x=x+1
end
d
3.times do
print "Ho! “
end
0.upto(9) do |x|
x ""
print x,
end
[ 1..5 ].each {|val| puts “ #{val} ” }
for i in ['fee', 'fi', 'fo', 'fum']
print i, " "
end
for i in 1..3
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 ...
end
for i in 1..100
print "Now at #{i}. Restart? "
retry if gets =~ /^y/i
end
Agora você programa em Ruby!
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
de configuração;
Né pra repetir
código
ó
não,
rapá!
€ Projeto
“Depot” do livro “Agile Web
Development With Ruby”;
€ Aplicação
€ Uma
de vendas de produtos a clientes;
interfaces p
para clientes,, outra p
para a
administração;
rails depot #sério, é só isso =P
README
Documentação
Rakefile
Arquivo de build
components/
Esqueça =P
doc/
Mais documentação
lib/
Código genérico da aplicação
script/
Scripts de build
vendor/
d /
Pl i para a sua aplicação
Plugins
li
ã
app/
Código da sua aplicação!
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
rake db:migrate
ruby script/generate model product
class CreateProducts < ActiveRecord::Migration
def self.up
create_table
_
:products
p
do |
|t|
|
t.column :title, :string
t.column :description, :text
t l
t.column
:image_url,
i g
l :string
ti g
t.column :price, :decimal, :precision =>
8, :scale => 2, :default => 0
end
end
def self.down
self down
drop_table :products
end
end
€O
seu b
banco d
de d
dados
d com controle
l d
de
versão!
€ Define
tabelas, adiciona linhas, cria índices e
ainda faz a janta!
€ Contém
criar alterar
métodos utilitários para criar,
e remover tabelas, colunas e linhas;
€ Você
faz no “up” e desfaz no “down”, não se
esqueça
q ç da ordem!
€ :null
ll
– indica
i di se pode
d ser null
ll ou não
ã ((truefalse)
€ :limit
– indica o tamanho máximo do campo
€ :default
– indica o valor padrão do campo
€ :precision
€ :scale
– indica a precisão do número
– indica a escala do número (quantas
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
#não,, você não vai usar isso até o fim
def index
list
render :action => 'list'
end
def list
@ d t
@product_pages,
g
@ d t = paginate
@products
gi t :products,
d t
:per_page => 10
end
def show
@product = Product.find(params[:id])
end
def new
@product = Product.new
end
def create
@product = Product.new(params[:product])
if @product.save
p
flash[:notice] = 'Product was successfully
created.'
redirect to :action => 'list'
redirect_to
list
else
render :action => 'new'
end
end
def edit
@product = Product.find(params[:id])
end
deff update
d
d t
@product = Product.find(params[:id])
if @product.update_attributes(
@product update attributes(
params[:product])
flash[:notice] = 'Product
Product was
successfully updated.'
redirect_to :action => 'show' , :id =>
@product
else
render
d :action
ti => 'edit'
' dit'
end
end
rake db:migrate #rodando o migration
ruby script/server webrick #iniciando o
servidor
http://localhost:3000/admin
#voilá!
p
€ 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á!);
€
action_name
ti
– nome da
d action
ti que está
tá
executando;
€
headers – hash com os cabeçalhos HTTP (você
pode colocar novos se q
p
quiser);
);
€
params – parametros que vieram da requisição,
í
podem ser acessados usando símbolos
ou strings;
€
flash
fl
h – objeto
bj t que pode
d guardar
d uma mensagem
entre uma requisição e outra (como enviar uma
g
p
pra um redirect);
);
mensagem
€ 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?,
xhr?
ۃ
um hash de strings, onde você
ê pode passar
qualquer valor;
€ Você
só pode passar Strings;
€ Sempre
p
use o atributo “cookies” p
para enviar
cookies para o navegador, nunca envie
usando o atributo “headers”;
€ Representa
R
uma sessão
ã HTTP d
de um usuário
ái
com a aplicação;
€ Você
pode colocar valores dentro dela, como
se ela fosse um hash;
€ Os
coisa
valores podem ser qualquer coisa,
contanto que seja um objeto que possa ser
serializado;;
€ EVITE
colocar muita coisa na sessão;;
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
<%= link_to 'Voltar', :action => 'list' %>
€ form_tag
f
é uma ffunção
ã d
de ajuda
j d que gera
um formulário através de um bloco de
código;
€ render
:partial => ‘form’
form , vai “incluir”
incluir o
arquivo “_form” dentro da página
€ submit_tag
€ link_to
‘Editar’ gera um botão clicável
‘Editar’ :action => ‘show’ gera um
link p
para o método ‘show’ do controller
atual;
<%= error_messages_for
<%
error messages for 'product'
product %>
<!--[form:product]-->
<p><label for="product_name">Nome</label><br/>
<%=
% text_field
t t fi ld :product,
d t :name %></p>
% /
<p><label for="product_category">Categoria</label><br/>
<%= select
l
:product,
d
:category_id,
d @categories, :prompt => "Escolha
lh
uma categoria"%> </p>
p label for=
for "prod
ct label">Marca</label><br/>
Marca /label br/
<p><label
product_label
<%= 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,
existem
i t
outros
t
utilitários
tilitá i para ttodos
d os
outros componentes HTML;
€O
uso de símbolos, como em “text_field
d t :name”
” é para di
d vem o
:product,
dizer d
de onde
campo e que campo é que nós queremos
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 item
it
l ”d
l t
segundo
éo“
“value”
do select;
<%
% form_for
f
f :product,
d t :urll => { :action
ti => :create
t }d
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>
<%
% end
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
bj t real;
l
quall o objeto
€ De
resto é igual a form_tag;
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
€ Toda
T d
a validação
lid ã é definida
d fi id d
dentro d
do próprio
ó i
objeto do modelo;
€ Existem
diversos métodos utilitários para
diversos tipos de validação;
€ Se
nenhum dos métodos resolve o seu
problema, implemente o método “validate”;
€ As
mensagens aparecem em -> <%=
error_messages_for
_
g _
'product'
p
%>
ruby script/generate migration add_test_data
add test data
class AddTestData < ActiveRecord::Migration
g
def self.up
Product.create(
:title
titl => 'P
'Pragmatic
g ti V
Version
i C
Control'
t l' ,
:description => %{<p>With Subversion</p>},
:image
g _url => '/images/svn.jpg'
g
jpg ,
:price => 28.50)
end
d f self.down
def
lf d
Product.delete_all
end
end
<%= link_to ‘Remover',
{ :action => 'destroy',
y , :id => p
product },
: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
disponível
í l para ttodos
d os controllers;
t ll
€ Todo
o trabalho que possa ser de lógica das
views (como formatação, geração de
t
l t e etc)
t ) deve
d
f it por eles;
l
templates
ser feito
€ NAS
VIEWS NÃO PODE HAVER LÓGICA,
Ó
entendeu? Ou quer que desenhe?
<%
% fform_for(:picture,
f ( i t
:url => {:action => 'save'},
:html =>
> { :multipart =>
> true }) do |form|
%>
Comment:
<%= form.text_field("comment" ) %><br/>
Upload your picture:
<%= form.file_field("uploaded_picture"
( p
p
) %><br/>
<%= submit_tag("Upload file" ) %>
<% end %>
class Picture < ActiveRecord::Base
validates_format_of :content_type,
:with => /^image/,
:message => ""-- you can only
l upload
l d pictures“
i t
“
def uploaded_picture=(picture_field)
self.name
lf
= base_part_of(picture_field.original_filename)
b
f
f ld
l fl
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,
p
,
:filename => @picture.name,
:type => @picture.content_type,
:disposition =>
> "inline"
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 q
que você definiu lá no
migration, vira uma propriedade do objeto;
€ ‘save’
e ‘save!’, salva ou atualiza um objeto,
‘save’ retorna true se conseguir salvar, false
senão
ã ou o objeto
bj t for
f inválido,
i álid ‘‘save!’
!’ lança
l
uma exeção se não conseguir salvar ou se o
objeto for inválido;
‘d t ’
€ ‘destroy’
bj t d
remove um objeto
do b
banco d
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
valores
l
das
d propriedades
i d d d
do objeto
bj t e ttentam
t
enviar uma atualização para o banco de
dados;
‘
t ’
€ ‘create’
i um novo objeto
bj t com o hash
h h de
d
cria
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
produto
d t pode
d tter N it
itens);
)
€ Métodos
adicionados:
product(reload = false)
ƒ product=
ƒ build_product( hash )
ƒ create_product( hash )
ƒ
€ Define
D fi
o llado
d 1d
do relacionamento
l i
um para
muitos;
€ Adiciona
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
os métodos (e ainda outros...):
orders(force_reload=false)
orders(force
reload=false)
orders <<order
orders.push(order1, ...)
orders.replace(order1, ...)
orders.delete(order1, ...)
orders.destroy_all
orders.size
orders.empty?
d
?
class Article < ActiveRecord::Base
has_and_belongs_to_many :users
end
class User < ActiveRecord::Base
g _to_manyy :articles
has_and_belongs
end
Account.transaction do
p
(
)
account1.deposit(100)
account2.withdraw(100)
end
name = params[:name]
pos =
( ,
Order.find(:all,
:conditions => "name = '#{name}' and
pay_type
p
y_ yp = 'po'"
p )
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 =>
pay type = :pay_type
:pay type" ,
[["name
name = :name and 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
€ :first
– primeiro item a ser trazido;
– 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 " +
_
,p
products " +
" from line_items,
" where line_items.product_id = products.id " )
li = items[0]
puts "#{li.title}: #{li.quantity}x#{li.unit_price}
=>
> #{li.total_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/

Documentos relacionados