active record
Post on 09-Nov-2014
29 Views
Preview:
TRANSCRIPT
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Active Record Sabor Ruby.Gaston Ramos - ramos.gaston@gmail.com
1 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Acerca de mı:
Soy desarrollador web freenlace.
Programo en Ruby desde hace 2 anos.
Soy miembro de Ruby-AR y Ruby del Litoral.
Publique algunas bibliotecas en ruby.
Colabore con el proyecto RubySpec.
Traduccion del libro ”Rails 2.1 Que hay de Nuevo?”
2 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Agenda.
1 Intro
2 Convenciones
3 Conexion con la DB.
4 Asociasiones
5 Finders
6 Validaciones
7 Callbacks
8 Fin
3 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Active Record es un Patron de Diseno.
Basado en el patron ActiveRecord de Martin Fowler (”Patternsof Enterprise Architecture”)
”Un objeto que engloba una fila de una tabla o vista de labase de datos, encapsula el acceso a la base de datos, y agregalogica del dominio del problema sobre estos datos.”
4 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
La biblioteca de Ruby Active Record .
”Nunca he visto una implementacion de Active Record tancompleta y tan util como la de rails.”
Martin Fowler
5 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Active Record sigue el standard de ORM.
Active record sigue el standard de ORM y se diferencia de losdemas por que minimiza la cantidad de configuracionmediante el uso de un conjunto de convenciones.
6 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Active Record sigue el standard de ORM.
Una clase por tabla.
Un objeto por registro.
Las columnas como atributos de estos objetos.
7 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Convencion sobre configuracion
Don’t Repeat Yourself
8 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Una clase por Tabla.
Codigo SQL para crear la tabla users:
CREATE TABLE ‘users‘ (‘id‘ int(11) NOT NULL auto_increment,‘login‘ varchar(255) default NULL,‘crypted_password‘ varchar(255) default NULL,‘email‘ varchar(25,5) default NULL,PRIMARY KEY (‘id‘) ) ENGINE=InnoDB
9 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Una clase por Tabla.
Codigo del modelo en Active Record (Ruby):
class User < ActiveRecord::Baseend
10 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Uso de convenciones:
- Codigo
- Errores
+ Productividad
11 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Convencion sobre configuracion.
class User < ActiveRecord::Baseend
Sin archivos XML.
Sin archivos generados.
Cada cosa en un solo lugar.
12 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Columnas y atributos.
Los objetos de Active Record se corresponden con las filas oregistros de una tabla de la base de datos.
Sin embargo hemos visto que no hay atributos en nuestasdefiniciones de clases.
Esto por que Active Record los determina dinamicamente enruntime.
Active Record ”mira” el esquema dentro de la base de datos yconfigura las clases que mapean las tablas.
13 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Expresividad en el codigo
14 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Mucha Informacion en pocas lıneas de codigo
class User < ActiveRecord::Basehas_many :postsbelongs_to :group
validates_presence_of :login, passwordvalidates_uniqueness_of :loginvalidates_confirmation_of :password
end
15 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Expresividad: Codigo mas bello
+ Motivacion
- Stress
+ Ganas
+ Productividad
16 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
La biblioteca de Ruby Active Record .
Active Record fue construida para Ruby on Rails, y hace quesea facil el CRUD.
Ya va por la version 2.1.2 y viene con la version 2.1.2 de RoR.(Hace poco salio el RC 2.2)
Create.
Read.
Update.
Delete.
17 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Tablas y clases.
Por defecto Active Record asume que el nombre de latabla es la forma plural de nombre de la clase.Si el nombre de la clase contiene multiples palabrascapitalizadas, el nombre de la tabla lleva guion bajo entreestas palabras.
18 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Pero sin no te gusta, lo podes cambiar!.
class Persona < ActiveRecord::Baseset_table_name "persona"
end
19 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Primary Key.
Active Record asume que cada tabla ha de tener una clave primaria(normalmente llamada id).
Se asegura que este campo id sea unico para cada registro agregadoen la tabla.
Esta es una convencion que puede no gustarle a algunos puristas.
¿Por que debemos usar una clave primariaartificial como id ?
20 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Primary Key.
La razon es puramente practica!
El formato de los datos externos puedecambiar con el paso del tiempo.
Por ejemplo, tenemos una base de datos con expedientes, el numerodel expediente bien podrıa ser nuestra clave primaria.
¿Que pasa si despues de un ano se decide anteponerle una letra X atodos los numeros de expedientes?
Tendrıamos que cambiar todos los id en nuestro esquema, yactualizar todas las relaciones a la tabla expediente.
Todas estas cosas requieren trabajo.
21 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Primary Key.
Todos estos problemas desaparecen si usamos nuestro propio valorinterno como primary key.
Si vamos a comenzar un proyecto nuevo trataremos de seguir lasconvenciones, para tener que trabajar menos.
Y si tenemos que trabajar con una base de datos existente podemoscambiar esta convencion.
class Expediente < ActiveRecord::Baseself.primary_key = "nro_expediente"
end
22 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Primary Key, Composite Key.
Normalmente Active Record se toma el cuidado de crear un nuevovalor de primary key cuando agregamos un nuevo registro a un tabla.
Si nosotros no seguimos la convencion y utilizamos nuestro propiocampo de id, debemos encargarnos de poner un valor de id unicoantes de guardar un nuevo registro.
¿Que pasa con las claves primarias compuestas?
En principio AR no las soporta, pero podemos utilizar algun plugin,http://compositekeys.rubyforge.org/
23 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Foreign Keys
class User < ActiveRecord::Basebelongs_to :group
end
class Group < ActiveRecord::Basehas_many :users
end
En la tabla user vamos a necesitar un campo group id
tabla id
24 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Conexion con la Base de Datos
Active Record viene con soporte para DB2, Firebird, Frontbase,MySQL, Openbase, Oracle, Postgres, SQLite, SQL Server, andSybase databases.
Una de las formas de conectarnos a la Base de Datos es mediante eluso del metodo de clase establish connection
Cada conector tiene un pequeno conjunto de parametros conexiondiferente.
25 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Conexion con la Base de Datos
ActiveRecord::Base.establish_connection(:adapter => "mysql",:host => "rubylit.com.ar",:database => "wiki",:username => "railsuser",:password => "securepw"
)
26 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Realciones entre tablas
La mayorıa de las aplicaciones que hacemos requieren muchastablas que normalmente estan relacionadas.
En el esquema de base de datos estas relaciones se expresan atraves de claves primarias y claves foraneas.
Es muy de Bajo NivelNecesitamos algo un poco mas comodo
27 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Realciones entre tablas
Queremos tener la posibilidad de hacer algo como:
name = post.user.name
En vez de:
user_id = post.user_iduser = User.find(user_id)name = user.name
28 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Asociaciones
belongs_to
has_one
has_many
has_and_belongs_to_many
29 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Asociaciones
class Project < ActiveRecord::Base
belongs_to :portfoliohas_one :project_manager,
:conditions => "role = ’project_manager’"
has_many :milestoneshas_and_belongs_to_many :categories
end
30 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Asociaciones
Project#portfolio
Project#project_manager
Project#milestones
Project#categories
31 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Asociaciones
Project#portfolio = portfolio
Project#portfolio.nil?
Project#project_manager = project_manager,
Project#project_manager.nil?
Project#milestones.empty?
32 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Asociaciones
Project#milestones.size
Project#milestones << milestone
Project#milestones.delete(milestone)
Project#milestones.find(milestone_id)
Project#milestones.find(:all, options)
33 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Asociaciones
Project#milestones.create
Project#categories.empty?
Project#categories.size
Project#categories << category1
Project#categories.delete(category1)
34 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Uno a Uno
class Employee < ActiveRecord::Basehas_one :office, :dependent => :destroy
end
class Office < ActiveRecord::Basebelongs_to :employee
end
35 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
One to Many
class Manager < ActiveRecord::Basehas_many :employees, :dependent => :nullify
end
class Employee < ActiveRecord::Basebelongs_to :manager
end
36 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Muchos a muchos
Hay dos formas de construir una relacion de muchosa muchos, la primer forma usa has many con laopcion :through y un modelo de union.
37 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Muchos a muchos
class Assignment < ActiveRecord::Basebelongs_to :programmer # foreign key - programmer_idbelongs_to :project # foreign key - project_id
end
class Programmer < ActiveRecord::Basehas_many :assignmentshas_many :projects, :through => :assignments
end
class Project < ActiveRecord::Basehas_many :assignmentshas_many :programmers, :through => :assignments
end
38 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Muchos a muchos
La segunda forma usa has and belongs to many en ambosmodelos.
# foreign keys en la tabla de union
class Programmer < ActiveRecord::Basehas_and_belongs_to_many :projects
end
class Project < ActiveRecord::Basehas_and_belongs_to_many :programmers
end
39 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Find es el metodo principal en AR.
User.find(1)#<User id: 1, name: "Pablo", login: "gaston", password: "pepe">
# SQL ejecutado:
SELECT * FROM ‘users‘ WHERE (‘users‘.‘id‘ = 1)
# ---------------------------------------------------------
User.first#<User id: 1, name: "Pablo", login: "gaston", password: "pepe">
# SQL ejecutado:
SELECT * FROM ‘users‘ LIMIT 1
40 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Find es el metodo principal en AR.
User.all
[#<User id: 1, name: "Pablo", login: "gaston", password: "pepe">,#<User id: 2, name: "David Bner", login: "david", password: "ppp">,#<User id: 3, name: "Pepito", login: "pepe", password: "1234">]
# SQL ejecutado:
SELECT * FROM ‘users‘
41 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Find con condiciones.
User.find(:all,:conditions => {:name => "david"}
)# SQL ejecutado:
SELECT * FROM ‘users‘ WHERE (‘users‘.‘name‘ = ’david’)
# ---------------------------------------------------------
User.find(:all,:conditions =>{ :first_name => "Bruce",
:last_name => "Lee" } )# SQL ejecutado:
SELECT * FROM users WHERE(first_name =’Bruce’ and last_name = ’Lee’);
42 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Order by.
User.find(:all, :order => "name desc")
[#<User id: 3, name: "Pepito", login: "pepe", password: "1234">,#<User id: 1, name: "Pablo", login: "gaston", password: "pepe">,#<User id: 2, name: "David Bner", login: "david", password: "ppp">]
# SQL ejecutado ---------------------------------
Select * from Users ORDER BY name desc;
43 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Joins.
User.find(:all,:join => "LEFT JOIN comments ON
comments.post_id = id")
# ---------------------------------------------------
SQL ejecutado:
SELETC * FROM Users LEFT JOIN commentsON comments.post_id = id;
44 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Creacion.
user = User.new(:name => "David",:occupation => "Code Artist")
user.save
user.name # => "David"
# ----------------------------------------------
User.create(:name => "Pepito", :login => "pepe",:password => "1234")
45 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Creacion.Creacion de un nuevo objeto pasandole un bloque con ladescripcion de sus atributos
User.create(:first_name => ’Jamie’) do |u|u.is_admin = false
end
Creacion de un array de objetos nuevos usando un bloque. Elbloque se ejecuta una vez por cada nuevo objeto creado.
User.create([{:first_name => ’Jamie’},{:first_name => ’Jeremy’}]) do |u|
u.is_admin = falseend
46 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Creacion.
Esto tambien funciona para las asociaciones:
author.posts.create!(:title => "New on Edge") {|p|p.body = "More cool stuff!"
}
47 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
El metodo sum.
Acepta expresiones a partir de la version 2.1
Product.sum("price * 2")
# ---------------------------------------------------
SQL ejecutado:
SELECT sum(price * 2) AS sum_price_all_2 FROM ‘products‘
# ---------------------------------------------------
A partir de la version Rails 2.1 el valor de retorno por defecto (cuando nose encuentra ningun registro) es 0.
Account.sum(:balance, :conditions => ’1 = 2’)#=> 0
48 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
El metodo count.
Person.count(:conditions => "age > 26")
Person.count(’id’, :conditions => "age > 26")# Hace un COUNT(id)
Person.count(:conditions => "age > 26 AND job.salary > 60000",:joins => "LEFT JOIN jobs on jobs.person_id = person.id")
Person.count(:all, :conditions => "age > 26")# Hace un COUNT(*)
49 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Otros Finds
Finds alternativos:
User.find_by_sql("SELECT * from users")
User.find_by_name_and_login("David", "dhh")
User.find_or_create_by_name(’Bob’, :age => 40)
50 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Y mas... Finds
Finds, like, select
User.find( :all,:conditions => ["name like ?" , "#{name}%" ])
Talks.find( :all,:select => "title, speaker, recorded_on" )
51 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Validaciones
Active Record puede validar el contenido de objeto del modelo.
Estas validaciones se realizan automaticamente cuando el objeto segraba en la BD.
Si las validaciones fallan el objeto no se guarda y queda en memoriacon un estado invalido.
Active Record puede distinguir entre objetos que corresponden aregistros en la BD y los que no.
User.save User.new_record?
Update o insert segun cada caso.
52 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Validaciones
validate
(en cada operacion de grabado)
validate_on_create
validate_on_update
User.valid?
(lo podes consultar en cualquier momento)
53 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Validation Helpers
Active Record tiene un conjunto de metodos ”helpers” que agreganvalidaciones a nuestros modelos.
El nombre no puede estar vacıo.
La edad debe ser entre 18 y 90 anos, etc.
Estas validaciones ”comunes” las hacen los helpers.
54 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Validation Helpers
validates_format_of
validates_uniqueness_of
validates_acceptance_of
validates_associated
validates_confirmation_of
validates_exclusion_of
validates_inclusion_of
validates_length_of
validates_numericality_of
55 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Ejemplos de Validation Helpers
class User < ActiveRecord::Base
validates_confirmation_of :password
end
class User < ActiveRecord::Base
validates_length_of :password, :in => 6..20
validates_length_of :address, :minimum => 10,:message => "seems too short"
end
56 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Callbacks
Usando callbacks, Active Record te permite ”pariticipar” en esteproceso de monitoreo.
Con los callbacks podemos escribir codigo se invocara en cadaevento significante del objeto.
Active Records define 20 callbacks.
Por ejemplo before destroy que se ejecuta antes de que el metododestroy se llame.
57 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
model.save()
Nuevo registro
before validation
before validation on create
after validation
before save
before create
Insert
after create
after save
58 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
model.save()
Registro existente
before validation
before validation on update
after validation
after validation on update
before save
before update
Update
after update
after save
59 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
model.destroy()
before destroy
Delete
after destroy
60 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Algunas cosas nuevas de la version 2.1
Named scope
Query cache
Dirty attributes
61 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Final
Preguntas?
62 / 63
Active Record, sabor Ruby
Intro Convenciones Conexion con la DB. Asociasiones Finders Validaciones Callbacks Fin
Final, Referencias
Fin, Gracias por escucharReferencias:
http://ar.rubyonrails.com/
Agile Web Development with Rails - Second Edition
ISBN: 0-9776166-3-0
Mi blog acerca de Ruby:http://gastonramos.wordpress.com
63 / 63
Active Record, sabor Ruby
top related