Post on 08-Jul-2015
description
Utilizando Rails e PostgreSQL
Algumas Limitações do AR no Rails 2
Uso de funções e constraints no banco é ignorado
Chaves compostas estão fora de questão
Não podemos encadear finds
Não podemos mapear SQLs arbitrários em objetos
Como conviver com o Rails 2
Melhorar o suporte a constraints no bancogem install sexy_pg_constraintsconfig.active_record.schema_format = :sql
Ex.: create_table :books do |t| t.text :title, :null => false t.text :isbn, :null => false t.timestamps end constrain :books do |t| t.title :alphanumeric => true, :length_within => 3..50 t.isbn :unique => true, :blacklist => %w(badbook1 badbook2) end
Constraints geradas no banco
Indexes: "books_pkey" PRIMARY KEY, btree (id) "books_isbn_unique" UNIQUE, btree (isbn)Check constraints: "books_isbn_blacklist" CHECK (isbn <> ALL (ARRAY['badbook1'::text, 'badbook2'::text])) "books_title_alphanumeric" CHECK (title ~* '^[a-z0-9]+$'::text) "books_title_length_within" CHECK (length(title) >= 3 AND length(title) <= 50)
Em último caso...
O comando execute nas migrations é seu amigo :)Para isso não esqueça de utilizar:
config.active_record.schema_format = :sql
Chaves compostas
http://compositekeys.rubyforge.org/gem install composite_primary_keysrequire 'composite_primary_keys' # environment.rb
Ex.:
require 'composite_primary_keys'class Book < ActiveRecord::Base set_primary_keys :id, :isbnendBook.find(1, 'isbncode')
Chaves compostas
Também adiciona suporte a FKs compostasE podemos criar rotas com chaves compostas, como:
/controller/show/123000,ISBN123456
Não podemos encadear finds
Usar named_scopesEles podem ser encadeados
Usar conditions:Book.find(:all, :conditions => " id = 1 OR title ~* 'a' ")
Usar o find_by_sql:Book.find_by_sql("SELECT * FROM books ... ")
Mapeando SQLs para objetos
Podemos usar o find_by_sqlSolução muito frágil para junções, projeções, uniões, etc...
Para JOINs temos o :include e o :joins
Book.all(:include => :sales)SELECT * FROM "books"SELECT "sales.*" FROM "sales" WHERE ("sales".book_id IN (1,2,3,4)) ORDER BY created_at asc)
Mapeando SQLs para objetos
Para JOINs temos o :include e o :joins
Book.all(:joins => :sales)SELECT "books".* FROM "books" INNER JOIN "sales" ON "books".id = "sales".book_id
Mapeando SQLs para objetos
Utilizar visõesComeçamos pela migration:
execute "CREATE OR REPLACE VIEW book_sales ASSELECT b.id AS book_id, s.id as sale_id, b.title, count(s.*) FROM books b JOIN sales s ON s.book_id = b.id"
Mapeando SQLs para objetos
Depois criamos um modelo para a nossa visão:
class BookSale < ActiveRecord::Base belongs_to :book belongs_to :salesend
Extensões para o PG no AR
https://github.com/softa/activerecord-postgres-hstoreSuporte ao tipo HStore do PostgreSQL para dados com atributos dinâmicos
https://github.com/tenderlove/texticleSuporte ao mecanismo de FTSSuporte ao módulo pg_trgm para comparação de trigramas
https://github.com/funny-falcon/activerecord-postgresql-arrays
Suporte ao tipo array de inteiroshttps://github.com/afair/postgresql-cursor
Uso de cursores no PostgreSQL
Melhorias no Rails 3
O AR 3 agora entende o conceito de relações! (Arel)Posso aplicar uma operação sobre um objeto que representa uma relação e o retorno será uma nova relação
Por que migrar para o Rails 3?
Encadeamento de operaçõesBook.where('id = ?', 0).where("title ~ ? ", 'a')
Inclusive com JOINSBook.where('books.id = ?', 0).joins(:sales)
Conversão de objeto relação para SQLBook.where('books.id = ?', 0).joins(:sales).to_sql
Tudo carregado para arrays de forma "lazy"Para mais info vejam:
http://m.onkey.org/2010/1/22/active-record-query-interface
Por que migrar para o Rails 3?
Possibilita o uso de ORMs alternativos como o excelente Sequel:
http://sequel.rubyforge.org/O Sequel ainda é bem mais completo que o AR 3, um ORM com a perspectiva de quem entende SQL.
Outra opção interessante é o DataMapper (esse fica para outra palestra)
Algumas vantagens do Sequel
Permite operações como UNION, INTERSECT e EXCEPT
Suporta CTE (consultas com WITH e WITH RECURSIVE)
Permite mostrar todos os SQLs gerados pelo ORM
Desvantagens do Sequel
Sem suporte de alguns plugins famosos do RailsDeviseAuthlogic
Utilizando o Sequel com o Rails 3
Adicionar ao Gemfile
gem 'sequel-rails'
Executar
bundle install
Utilizando o Sequel com o Rails 3
Modifique o arquivo config/application.rb de...require 'rails/all'...
para...#require 'rails/all'require "action_controller/railtie"require "sequel-rails/railtie"require "action_mailer/railtie"require "rails/test_unit/railtie"...
Utilizando o Sequel com o Rails 3
Qualquer plugin do rails que utilize diretamente o AR deve ser trocado por um equivalente para o Sequel
Por exemplo:Paperclip para sequel é a gem: sequel_paperclip
Diferenças entre Sequel e AR
Nomes de adptadores podem mudar (database.yml)
AR:adapter: postgresql
Sequeladapter: postgres
Diferenças entre Sequel e AR
Migration no AR:create_table :menu_items do |t| t.text :name, :null => false t.text :description, :null => falseend
Migration no Sequelcreate_table :menu_items do primary_key :id Text :name, :null => false Text :description, :null => falseend
Diferenças entre Sequel e AR
Qual valor é inserido na coluna quando eu não informo nenhum valor no método create?
ARNULL
SequelDEFAULT
Diferenças entre Sequel e AR
Métodos find*
AR (procura por id)MenuItem.find 1Tenho métodos find_by_
Sequel (exige o campo e valor de busca)MenuItem.find :id => 1Não tenho métodos find_by
Plugins nativos do Sequel
RcteTreeModelo de árvore usando RECURSIVE CTEs
UpdatePrimaryKeyPara usar chaves naturais
IdentityMapCria uma relação de 1-1 entre objetos e linhas do banco
LazyAttributesBusca campos para o modelo sob demanda.
Extensões para o PG no Sequel
https://github.com/gucki/sequel_column_type_arrayTipos array de inteiro e de varchar no banco
https://github.com/jeremyevans/sequel_postgresql_triggersGatilhos em PL/pgSQL criados de forma transparente para gerenciar: updated_at, created_at, cache de contadores e cache de somas
https://github.com/jeremyevans/sequel_pgAcelera comandos SELECT
Muito Obrigado!
Daniel WeinmannEmail: danielweinmann@gmail.comTwitter: @danielweinmann
Diogo BiazusEmail: diogob@gmail.comTwitter: @dbiazus