Está en la página 1de 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Active Record Sabor Ruby.


Gast on Ramos - ramos.gaston@gmail.com
Active Record, sabor Ruby 1 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Acerca de m :
Soy desarrollador web freenlace. Programo en Ruby desde hace 2 a nos. Soy miembro de Ruby-AR y Ruby del Litoral. Publiqu e algunas bibliotecas en ruby. Colabor e con el proyecto RubySpec. Traducci on del libro Rails 2.1 Qu e hay de Nuevo?

Active Record, sabor Ruby 2 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Agenda.
1 2 3 4 5 6 7 8

Intro Convenciones Conexi on con la DB. Asociasiones Finders Validaciones Callbacks Fin
Active Record, sabor Ruby 3 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Active Record es un Patr on de Dise no.


Basado en el patr on ActiveRecord de Martin Fowler (Patterns of Enterprise Architecture) Un objeto que engloba una la de una tabla o vista de la base de datos, encapsula el acceso a la base de datos, y agrega l ogica del dominio del problema sobre estos datos.

Active Record, sabor Ruby 4 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

La biblioteca de Ruby Active Record .

Nunca he visto una implementaci on de Active Record tan completa y tan u til como la de rails. Martin Fowler

Active Record, sabor Ruby 5 / 63

Intro

Convenciones

Conexi on 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 los dem as por que minimiza la cantidad de conguraci on mediante el uso de un conjunto de convenciones.

Active Record, sabor Ruby 6 / 63

Intro

Convenciones

Conexi on 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.

Active Record, sabor Ruby 7 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Convenci on sobre conguraci on Dont Repeat Yourself

Active Record, sabor Ruby 8 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Una clase por Tabla.

C odigo 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

Active Record, sabor Ruby 9 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Una clase por Tabla.

C odigo del modelo en Active Record (Ruby):

class User < ActiveRecord::Base end

Active Record, sabor Ruby 10 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Uso de convenciones: - C odigo - Errores + Productividad


Active Record, sabor Ruby 11 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Convenci on sobre conguraci on.

class User < ActiveRecord::Base end Sin archivos XML. Sin archivos generados. Cada cosa en un s olo lugar.

Active Record, sabor Ruby 12 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Columnas y atributos.

Los objetos de Active Record se corresponden con las las o registros de una tabla de la base de datos. Sin embargo hemos visto que no hay atributos en nuestas deniciones de clases. Esto por que Active Record los determina din amicamente en runtime. Active Record mira el esquema dentro de la base de datos y congura las clases que mapean las tablas.

Active Record, sabor Ruby 13 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Expresividad en el c odigo

Active Record, sabor Ruby 14 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Mucha Informaci on en pocas l neas de c odigo

class User < ActiveRecord::Base has_many :posts belongs_to :group validates_presence_of :login, password validates_uniqueness_of :login validates_confirmation_of :password end

Active Record, sabor Ruby 15 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Expresividad: C odigo m as bello + Motivaci on - Stress + Ganas + Productividad


Active Record, sabor Ruby 16 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

La biblioteca de Ruby Active Record .


Active Record fue construida para Ruby on Rails, y hace que sea f acil el CRUD. Ya va por la versi on 2.1.2 y viene con la versi on 2.1.2 de RoR. (Hace poco sali o el RC 2.2)

Create. Read. Update. Delete.

Active Record, sabor Ruby 17 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Tablas y clases.

Por defecto Active Record asume que el nombre de la tabla es la forma plural de nombre de la clase. Si el nombre de la clase contiene m ultiples palabras capitalizadas, el nombre de la tabla lleva gui on bajo entre estas palabras.

Active Record, sabor Ruby 18 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Pero sin no te gusta, lo pod es cambiar!.

class Persona < ActiveRecord::Base set_table_name "persona" end

Active Record, sabor Ruby 19 / 63

Intro

Convenciones

Conexi on 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 u nico para cada registro agregado en la tabla. Esta es una convenci on que puede no gustarle a algunos puristas.

Por que debemos usar una clave primaria articial como id ?

Active Record, sabor Ruby 20 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Primary Key.

La raz on es puramente pr actica! El formato de los datos externos puede cambiar con el paso del tiempo.
Por ejemplo, tenemos una base de datos con expedientes, el n umero del expediente bien podr a ser nuestra clave primaria. Que pasa si despu es de un a no se decide anteponerle una letra X a todos los n umeros de expedientes? Tendr amos que cambiar todos los id en nuestro esquema, y actualizar todas las relaciones a la tabla expediente. Todas estas cosas requieren trabajo.
Active Record, sabor Ruby 21 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Primary Key.

Todos estos problemas desaparecen si usamos nuestro propio valor interno como primary key. Si vamos a comenzar un proyecto nuevo trataremos de seguir las convenciones, para tener que trabajar menos. Y si tenemos que trabajar con una base de datos existente podemos cambiar esta convenci on.

class Expediente < ActiveRecord::Base self.primary_key = "nro_expediente" end

Active Record, sabor Ruby 22 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Primary Key, Composite Key.

Normalmente Active Record se toma el cuidado de crear un nuevo valor de primary key cuando agregamos un nuevo registro a un tabla. Si nosotros no seguimos la convenci on y utilizamos nuestro propio campo de id, debemos encargarnos de poner un valor de id u nico antes de guardar un nuevo registro. Qu e pasa con las claves primarias compuestas? En principio AR no las soporta, pero podemos utilizar alg un plugin, http://compositekeys.rubyforge.org/

Active Record, sabor Ruby 23 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Foreign Keys
class User < ActiveRecord::Base belongs_to :group end class Group < ActiveRecord::Base has_many :users end

En la tabla user vamos a necesitar un campo group id

tabla id
Active Record, sabor Ruby 24 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Conexi on con la Base de Datos

Active Record viene con soporte para DB2, Firebird, Frontbase, MySQL, Openbase, Oracle, Postgres, SQLite, SQL Server, and Sybase databases. Una de las formas de conectarnos a la Base de Datos es mediante el uso del m etodo de clase establish connection Cada conector tiene un peque no conjunto de par ametros conexion diferente.

Active Record, sabor Ruby 25 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Conexi on con la Base de Datos

ActiveRecord::Base.establish_connection( :adapter => "mysql", :host => "rubylit.com.ar", :database => "wiki", :username => "railsuser", :password => "securepw" )

Active Record, sabor Ruby 26 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Realciones entre tablas


La mayor a de las aplicaciones que hacemos requieren muchas tablas que normalmente est an relacionadas. En el esquema de base de datos estas relaciones se expresan a trav es de claves primarias y claves for aneas.

Es muy de Bajo Nivel Necesitamos algo un poco m as c omodo

Active Record, sabor Ruby 27 / 63

Intro

Convenciones

Conexi on 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_id user = User.find(user_id) name = user.name

Active Record, sabor Ruby 28 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Asociaciones

belongs_to has_one has_many has_and_belongs_to_many

Active Record, sabor Ruby 29 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Asociaciones

class Project < ActiveRecord::Base belongs_to :portfolio has_one :project_manager, :conditions => "role = project_manager" has_many :milestones has_and_belongs_to_many :categories end

Active Record, sabor Ruby 30 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Asociaciones

Project#portfolio Project#project_manager Project#milestones Project#categories

Active Record, sabor Ruby 31 / 63

Intro

Convenciones

Conexi on 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?

Active Record, sabor Ruby 32 / 63

Intro

Convenciones

Conexi on 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)

Active Record, sabor Ruby 33 / 63

Intro

Convenciones

Conexi on 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)

Active Record, sabor Ruby 34 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Uno a Uno

class Employee < ActiveRecord::Base has_one :office, :dependent => :destroy end class Office < ActiveRecord::Base belongs_to :employee end

Active Record, sabor Ruby 35 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

One to Many

class Manager < ActiveRecord::Base has_many :employees, :dependent => :nullify end class Employee < ActiveRecord::Base belongs_to :manager end

Active Record, sabor Ruby 36 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Muchos a muchos

Hay dos formas de construir una relaci on de muchos a muchos, la primer forma usa has many con la opci on :through y un modelo de uni on.

Active Record, sabor Ruby 37 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Muchos a muchos
class Assignment < ActiveRecord::Base belongs_to :programmer # foreign key - programmer_id belongs_to :project # foreign key - project_id end class Programmer < ActiveRecord::Base has_many :assignments has_many :projects, :through => :assignments end class Project < ActiveRecord::Base has_many :assignments has_many :programmers, :through => :assignments end
Active Record, sabor Ruby 38 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Muchos a muchos
La segunda forma usa has and belongs to many en ambos modelos. # foreign keys en la tabla de uni on class Programmer < ActiveRecord::Base has_and_belongs_to_many :projects end class Project < ActiveRecord::Base has_and_belongs_to_many :programmers end

Active Record, sabor Ruby 39 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Find es el m etodo 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

Active Record, sabor Ruby 40 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Find es el m etodo 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

Active Record, sabor Ruby 41 / 63

Intro

Convenciones

Conexi on 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);
Active Record, sabor Ruby 42 / 63

Intro

Convenciones

Conexi on 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;

Active Record, sabor Ruby 43 / 63

Intro

Convenciones

Conexi on 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 comments ON comments.post_id = id;

Active Record, sabor Ruby 44 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Creaci on.

user = User.new(:name => "David", :occupation => "Code Artist") user.save user.name # => "David" # ---------------------------------------------User.create(:name => "Pepito", :login => "pepe", :password => "1234")

Active Record, sabor Ruby 45 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Creaci on.
Creaci on de un nuevo objeto pas andole un bloque con la descripci on de sus atributos User.create(:first_name => Jamie) do |u| u.is_admin = false end Creaci on de un array de objetos nuevos usando un bloque. El bloque se ejecuta una vez por cada nuevo objeto creado. User.create([{:first_name => Jamie}, {:first_name => Jeremy}]) do |u| u.is_admin = false end

Active Record, sabor Ruby 46 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Creaci on.

Esto tambi en funciona para las asociaciones: author.posts.create!(:title => "New on Edge") {|p| p.body = "More cool stuff!" }

Active Record, sabor Ruby 47 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

El m etodo sum.
Acepta expresiones a partir de la versi on 2.1

Product.sum("price * 2")
# --------------------------------------------------SQL ejecutado: SELECT sum(price * 2) AS sum_price_all_2 FROM products # --------------------------------------------------A partir de la versi on Rails 2.1 el valor de retorno por defecto (cuando no se encuentra ning un registro) es 0.

Account.sum(:balance, :conditions => 1 = 2) #=> 0


Active Record, sabor Ruby 48 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

El m etodo 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(*)

Active Record, sabor Ruby 49 / 63

Intro

Convenciones

Conexi on 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)

Active Record, sabor Ruby 50 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Y m as... Finds

Finds, like, select User.find( :all, :conditions => ["name like ?" , "#{name}%" ]) Talks.find( :all, :select => "title, speaker, recorded_on" )

Active Record, sabor Ruby 51 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Validaciones

Active Record puede validar el contenido de objeto del modelo. Estas validaciones se realizan autom aticamente cuando el objeto se graba en la BD. Si las validaciones fallan el objeto no se guarda y queda en memoria con un estado inv alido. Active Record puede distinguir entre objetos que corresponden a registros en la BD y los que no. User.save User.new_record? Update o insert seg un cada caso.

Active Record, sabor Ruby 52 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Validaciones

validate (en cada operaci on de grabado) validate_on_create validate_on_update User.valid? (lo pod es consultar en cualquier momento)

Active Record, sabor Ruby 53 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Validation Helpers

Active Record tiene un conjunto de m etodos helpers que agregan validaciones a nuestros modelos. El nombre no puede estar vac o. La edad debe ser entre 18 y 90 a nos, etc. Estas validaciones comunes las hacen los helpers.

Active Record, sabor Ruby 54 / 63

Intro

Convenciones

Conexi on 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
Active Record, sabor Ruby 55 / 63

Intro

Convenciones

Conexi on 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

Active Record, sabor Ruby 56 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Callbacks

Usando callbacks, Active Record te permite pariticipar en este proceso de monitoreo. Con los callbacks podemos escribir c odigo se invocar a en cada evento signicante del objeto. Active Records dene 20 callbacks. Por ejemplo before destroy que se ejecuta antes de que el m etodo destroy se llame.

Active Record, sabor Ruby 57 / 63

Intro

Convenciones

Conexi on 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

Active Record, sabor Ruby 58 / 63

Intro

Convenciones

Conexi on 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
Active Record, sabor Ruby 59 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

model.destroy()

before destroy

Delete
after destroy

Active Record, sabor Ruby 60 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Algunas cosas nuevas de la versi on 2.1

Named scope Query cache Dirty attributes

Active Record, sabor Ruby 61 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Final

Preguntas?

Active Record, sabor Ruby 62 / 63

Intro

Convenciones

Conexi on con la DB.

Asociasiones

Finders

Validaciones

Callbacks

Fin

Final, Referencias

Fin, Gracias por escuchar


Referencias: 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

Active Record, sabor Ruby 63 / 63