ruby on rails i - modelos
DESCRIPTION
Uma breve apresentação explicando as funcionalidades básicas dos modelos com o ActiveRecord como ORM.TRANSCRIPT
![Page 1: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/1.jpg)
Ruby on Rails I
Tiago Ferreira Lima - fltiago
![Page 2: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/2.jpg)
Roteiro
• Começando com Rails• Migrações• ActiveRecord
• Validações
• Callbacks
• Associações
• Query Interface
• Mãos à obra
![Page 3: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/3.jpg)
Começando com Rails
![Page 4: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/4.jpg)
O que é Rails?
• Framework para desenvolvimento de aplicações Web
• Filosofia Rails• DRY - “Don’t Repeat Yourself”
• Convenção sobre configuração
• REST
![Page 5: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/5.jpg)
MVC
• Arquitetura de software baseada em Modelos, Views e Controladores
• Benefícios• Isolamento da lógica de negócios
• Clara separação de responsabilidades, facilitando a manutenção
![Page 6: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/6.jpg)
Os componentes do Rails
• Action Pack• Action Controller
• Action Dispatch
• Action View
• Action Mailer
![Page 7: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/7.jpg)
Os componentes do Rails
• Active Model• Active Record• Active Resource• Active Support• Railties
![Page 8: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/8.jpg)
Instalando Rails
• Linux e Mac (se já houver o rubygems)
• Windows• Rails Installer FTW! http://
railsinstaller.org/
$ gem install rails$ rails -‐-‐version
![Page 9: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/9.jpg)
Criando uma aplicação Rails
• Um único comando$ rails new nome_do_app
![Page 10: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/10.jpg)
Estrutura de uma aplicação Rails
![Page 11: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/11.jpg)
Migrações
![Page 12: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/12.jpg)
Migrações
• Um jeito bonito e organizado de alterar o banco de dados
• Vantagens• Não há necessidade de comunicar outros
desenvolvedores que houve mudança no BD
• Não há necessidade de conhecer a linguagem específica do SQL
• É independente de banco de dados, suporte a diversos SGBDs
![Page 13: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/13.jpg)
Migrações
• Estrutura das migrações:class CreateProducts < ActiveRecord::Migration
def up create_table :products do |t| t.string :name t.text :description t.timestamps end end def down drop_table :products endend
![Page 14: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/14.jpg)
Migrações
• Ou:class CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.text :description t.timestamps end endend
![Page 15: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/15.jpg)
Migrações
• Olhando mais de perto as migraçõesclass CreateProducts < ActiveRecord::Migration
def up create_table :products do |t| t.string :name t.text :description t.timestamps end end def down drop_table :products endend
![Page 16: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/16.jpg)
Migrações
• Métodos:add_columnadd_indexadd_referenceadd_timestampscreate_tablecreate_join_tabledrop_table (must supply a block)drop_join_table (must supply a block)remove_timestampsrename_columnrename_indexremove_referencerename_table
![Page 17: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/17.jpg)
Migrações
• Types::binary:boolean:date:datetime:decimal:float:integer:primary_key:string:text:time:timestamp
![Page 18: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/18.jpg)
E finalmente, criando uma migração
• Com o model$ rails generate model Product name:string description:text
# Geraclass CreateProducts < ActiveRecord::Migration def change create_table :products do |t| t.string :name t.text :description t.timestamps end endend
![Page 19: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/19.jpg)
E finalmente, criando uma migração
• Uma migração por si só
• Convenções facilitam a criação
$ rails generate migration AddPartNumberToProducts
# Geraclass AddPartNumberToProducts < ActiveRecord::Migration def change endend
$ rails generate migration AddPartNumberToProducts part_number:string
class AddPartNumberToProducts < ActiveRecord::Migration def change add_column :products, :part_number, :string endend
![Page 20: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/20.jpg)
O mais importante
• Executando migrações
• Voltando uma migração
$ rake db:migrate
$ rake db:migrate VERSION=20080906120000
$ rake db:rollback
$ rake db:rollback STEP=3
![Page 21: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/21.jpg)
ActiveRecord
![Page 22: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/22.jpg)
ActiveRecord
• É a implementação de um padrão de mapeamento objeto-relacional (ORM)
• Conecta classes e atributos a tabelas e colunas
![Page 23: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/23.jpg)
ActiveRecord
• Permite:• Migrações
• Validações
• Associações
• Callbacks
• Transações
• Entre outras coisas...
![Page 24: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/24.jpg)
Validações
![Page 25: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/25.jpg)
Visão geral
• Garante que apenas dados válidos serão inseridos no banco de dados
• Existem diversos meios de garantir a validação de um dado: restrições dos banco de dados, validações em client-side, validações em controladores e validações em modelo
• Vamos nos concentrar em modelos, é um jeito Rails de fazer validações
![Page 26: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/26.jpg)
Quando uma validação acontece?
• Antes que os objetos sejam salvos no banco de dados
• Métodos que disparam validaçõescreatecreate!savesave!updateupdate_attributesupdate_attributes!
![Page 27: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/27.jpg)
Exemplo de uso
• valid? e invalid?class Person < ActiveRecord::Base validates :name, :presence: trueend >> p = Person.new=> #<Person id: nil, name: nil>>> p.errors=> {} >> p.valid?=> false>> p.errors=> {name:["can't be blank"]} >> p = Person.create=> #<Person id: nil, name: nil>>> p.errors=> {name:["can't be blank"]} >> p.save=> false >> p.save!=> ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
![Page 28: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/28.jpg)
Validations Helpers
• Aceitaçãoclass Person < ActiveRecord::Base validates :terms_of_service, acceptance: trueend
class Library < ActiveRecord::Base has_many :books validates_associated :booksend
class Person < ActiveRecord::Base validates :email, confirmation: true validates :email_confirmation, presence: trueend
• Valida modelos associados
• Confirmação e Presença
![Page 29: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/29.jpg)
Validations Helpers
• Exclusãoclass Account < ActiveRecord::Base validates :subdomain, exclusion: { in: %w(www us ca jp), message: "Subdomain %{value} is reserved." }end
class Product < ActiveRecord::Base validates :legacy_code, format: { with: /\A[a-‐zA-‐Z]+\z/, message: "Only letters allowed" }end
class Coffee < ActiveRecord::Base validates :size, inclusion: { in: %w(small medium large), message: "%{value} is not a valid size" }end
• Formatação
• Inclusão
![Page 30: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/30.jpg)
Validations Helpers
• Tamanhoclass Person < ActiveRecord::Base validates :name, length: { minimum: 2, maximum: 500 } validates :password, length: { in: 6..20 } validates :registration_number, length: { is: 6 }end
class Player < ActiveRecord::Base validates :points, numericality: true validates :games_played, numericality: { only_integer: true }end
class Account < ActiveRecord::Base validates :email, uniqueness: trueend
• Numeração
• Unicidade
![Page 31: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/31.jpg)
Callbacks
![Page 32: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/32.jpg)
Visão Geral
• Callbacks são uma forma de associar comportamento a determinados momentos do ciclo de vida de um modelo
• É possível escrever códigos que executem sempre que um objeto do ActiveRecord é criado, salvado, atualizado, deletado, validado ou carregado do banco de dados.
![Page 33: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/33.jpg)
Exemplos de uso
class User < ActiveRecord::Base validates :login, :email, presence: true before_validation :ensure_login_has_a_value protected def ensure_login_has_a_value if login.nil? self.login = email unless email.blank? end endend
class User < ActiveRecord::Base validates :login, :email, presence: true before_create do |user| user.name = user.login.capitalize if user.name.blank? endend
![Page 34: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/34.jpg)
Callbacks disponíveis
• Criando um objeto before_validationafter_validationbefore_savearound_savebefore_createaround_createafter_createafter_save
before_validationafter_validationbefore_savearound_savebefore_updatearound_updateafter_updateafter_save
• Atualizando um objeto
![Page 35: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/35.jpg)
Callbacks disponíveis
• Destruindo um objetobefore_destroyaround_destroyafter_destroy
![Page 36: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/36.jpg)
Associações
![Page 37: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/37.jpg)
Visão Geral
• Relacionamentos/associações são parte central dos bancos de dados relacionais
• ActiveRecord facilita as interações entre modelos
![Page 38: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/38.jpg)
Exemplo de uso
class Customer < ActiveRecord::Base has_many :orders, dependent: :destroyend class Order < ActiveRecord::Base belongs_to :customerend
# rails console$ @orders = @customer.orders$ @costumer = @order.customer
![Page 39: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/39.jpg)
Tipos de associações
• Tipos:belongs_tohas_onehas_manyhas_many :throughhas_one :throughhas_and_belongs_to_many
![Page 40: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/40.jpg)
Query Interface
![Page 41: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/41.jpg)
Visão Geral
• Internface que define acesso ao banco e instancia os objetos
• ActiveRecord facilita a interação entre o objeto e banco de dados
![Page 42: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/42.jpg)
Retornando um simples objeto
• Usando a primary key (find)# Encontra um client com id = 10client = Client.find(10)# => #<Client id: 10, first_name: "Ryan">
# O SQL gerado por RailsSELECT * FROM clients WHERE (clients.id = 10) LIMIT 1
• Usando métodos já prontosclient = Client.last# => #<Client id: 221, first_name: "Russel">
SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
client = Client.first# => #<Client id: 1, first_name: "Lifo">
SELECT * FROM clients LIMIT 1
![Page 43: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/43.jpg)
Retornando muitos objetos
• Usando as primary keys (find)client = Client.find([1, 10]) # Or even Client.find(1, 10)# => [#<Client id: 1, first_name: "Lifo">, #<Client id: 10, first_name: "Ryan">]
SELECT * FROM clients WHERE (clients.id IN (1,10))
• Retornando todos os elementos de um objeto
# Só existem dois elementos guardados no bancoclients = Client.all# => [#<Client id: 221, first_name: "Russel">, #<Client id: 10, first_name: "Ryan">]
![Page 44: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/44.jpg)
Condições
• String puraclient = Client.where("orders_count = '2'") # => [#<Client id: 1, first_name: "Lifo", orders_count: 2>, #<Client id: 10, first_name: "Ryan", orders_count: 2>]
SELECT * FROM clients WHERE (clients.orders_count = '2')
• Passando Array como parâmetroClient.where("orders_count = ?", params[:orders])Client.where("orders_count = ? AND locked = ?", params[:orders], false)Client.where("created_at >= :start_date AND created_at <= :end_date", {start_date: params[:start_date], end_date: params[:end_date]})
Client.where(created_at: (params[:start_date].to_date)..(params[:end_date].to_date))
SELECT "clients".* FROM "clients" WHERE ("clients"."created_at" BETWEEN '2010-‐09-‐29' AND '2010-‐11-‐30')
![Page 45: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/45.jpg)
Ordem e Seleção
• OrdemClient.order("created_at DESC")# ouClient.order("created_at ASC")
Client.order("orders_count ASC, created_at DESC")
• Seleção de colunaClient.select("viewable_by, locked")
SELECT viewable_by, locked FROM clients
![Page 46: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/46.jpg)
Limite e Offset
• Limite e OffsetClient.limit(5).offset(30)
SELECT * FROM clients LIMIT 5 OFFSET 30
![Page 47: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/47.jpg)
Mãos à obra
![Page 48: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/48.jpg)
Caso de uso
• O usuário, possui nome, e-mail, sobrenome, idade
• O usuário não existe sem nome e e-mail
• O e-mail deve ser formatado de maneira correta
• Um usuário possui vários livros
![Page 49: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/49.jpg)
Caso de uso
• O livro deve ter nome e pode ter edição
• Os livros não existem sem os usuários
• Deve ser possível consultar os 5 livros mais recentes de um usuário
• Deve ser possível procurar usuários por nome e sobrenome
![Page 50: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/50.jpg)
Caso de uso
• Deverá ser possível procurar por usuário entre um determinado intervalo de idade
![Page 51: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/51.jpg)
Referências
• Rails Guides - http://guides.rubyonrails.org/
• Ruby on Rails 3 Tutorial - http://ruby.railstutorial.org/
• Design Patterns in Ruby - Russ Olsen
![Page 52: Ruby on Rails I - Modelos](https://reader033.vdocuments.pub/reader033/viewer/2022060122/559626071a28ab6f4a8b45cb/html5/thumbnails/52.jpg)
Obrigado!