• Nenhum resultado encontrado

€ 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 administração;

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 esqueça da ordem!q ç

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)

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 € 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?, xhr?

É ê

€ É 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

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 -> <%= error_messages_for 'product' %>_ g _ p

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, entendeu? Ou quer que desenhe?

% 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;

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/

Documentos relacionados