Relaciones en Rails 3(1 1,1 n,n n)

Post on 24-Jul-2015

348 views 0 download

description

Rails

Transcript of Relaciones en Rails 3(1 1,1 n,n n)

Desarrollo web con Ruby on Rails 3ActiveRecord: asociaciones entre clases

Áncor González Sosa Imobach González Sosa

Banot.nethttp://www.banot.net/

Octubre de 2010

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 1 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 2 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 3 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 4 / 64

Los objetos no "viven" aislados

ActiveRecord ofrece mecanismos para relacionar modelosAPI potente, flexible y fácil de usarLas relaciones se declaran estilo "macro"Siguiendo las convenciones, se reduce al mínimo el código

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 5 / 64

¿Puede ser más simple?

class Artist < ActiveRecord::Basehas_many :albums

end

class Album < ActiveRecord::Basebelongs_to :artist

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 6 / 64

¿Puede ser más simple?

album = Album.new(:title => "Born under a bad sign")albert = Artist.find_by_name("Albert King")album.artist = albertalbert.albums.each { |a| puts a.title }

gary = Artist.find_by_name("Gary Moore")gary.albums << Album.new(:title => "King of the blues")gary.albums.build(:title => "Wild frontier")

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 7 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 8 / 64

Especificación

class Company < ActiveRecord::Basehas_one :office

end

class Office < ActiveRecord::Basebelongs_to :company

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 9 / 64

Tablas

companiesidname string

officesidnumber stringarea integercompany_id integer

11

has_one

belongs_to

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 10 / 64

Referencias en las migraciones

Se puede usar el método references en la definición de tablas

create_table :offices do |t|t.string :numbert.decimal :areat.references :customer # customer_idt.timestamps

end

De todos modos, no deja de ser un entero:

create_table :offices do |t|t.string :numbert.decimal :areat.integer :customer_idt.timestamps

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 11 / 64

Métodos de belongs_to

association(force_reload = false)

office.company

association=(associate)

office.company = Company.first

build_association(attributes = {})

office.build_company(:name => "Banot.net")

create_association(attributes = {})

office.create_company(:name => "Inventiaplus")

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 12 / 64

Métodos de has_one

association(force_reload = false)

office.company

association=(associate)

office.company = Company.first

build_association(attributes = {})

office.build_company(:name => "Banot.net")

create_association(attributes = {})

office.create_company(:name => "Inventiaplus")

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 13 / 64

¿Cuándo se guardan los objetos?has_one

El objeto asociado se guarda al asignarlo para actualizar su claveajenaEl objeto reemplazado (si lo hubiera), también se guardaExcepto:

I Si falla una de las validaciones, se cancela la asignaciónI Si el extremo que tiene el has_one es nuevo, se esperará (a que

este se guarde)

Para asignar sin guardar, usar el método build

Si se asigna por el extremo que tiene el belongs_to, nunca seguardan los objetos

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 14 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 15 / 64

Especificación

class Artist < ActiveRecord::Basehas_many :albums

end

class Album < ActiveRecord::Basebelongs_to :artist

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 16 / 64

Tablas

artistsidname string

albumsidtitle stringartist_id integer

1n

has_many belongs_to

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 17 / 64

Métodos de has_many (I)

collection(force_reload = false)

artist.albums

collection<<(associate)

artist.albums << Album.new

delete(object)

artist.delete(album)

collection=(objects)

albums.class # Arrayoffice.albums = albums

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 18 / 64

Métodos de has_many (II)

collection_singular_ids / collection_singular_ids=

artist.album_ids # [1, 2]artist.album_ids = [1, 3]

clear

artist.albums.clearartist.albums # []

empty?

artist.albums.empty?

size

artist.albums.size

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 19 / 64

Métodos de has_many (III)

find(...)

artist.albums.find_by_year(2010)artist.albums.find(:conditions => { ... })

clear

artist.albums.clearartist.albums # []

exists?

artist.albums.exists?(:year => 2010)

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 20 / 64

Métodos de has_many (y IV)

collection.build(attributes = {})

a = artist.albums.build(:title => "Believe")a.new_record? # truea.save!

collection.create(attributes = {})

a = artist.albums.create(:title => "Asylum")a.new_record? # false

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 21 / 64

¿Cuándo se guardan los objetos?has_many

Los objetos asociados se guardan al asignarlosExcepto:

I Si falla la validación de cualquiera de ellos, la asignación secancela

I Si el extremo que tiene en has_many es nuevo, se esperará (hastaque se guarde)

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 22 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 23 / 64

Especificación

class Musician < ActiveRecord::Basehas_and_belongs_to_many :bands

end

class Band < ActiveRecord::Basehas_and_belongs_to_many :musicians

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 24 / 64

Tablas

bandsidname string

has_and_belongs_to_many

musiciansidname string

has_and_belongs_to_many

bands_musiciansband_id integermusician_id integer

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 25 / 64

La tabla intermedia

El nombre se forma contatenando los plurales de los nombres delas clasesSe ordenan alfabéticamenteHay que indicar que no precisa clave primaria

create_table :companies_offices, :id => false do |t|t.references :companyt.references :office

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 26 / 64

Parecidos con has_many

Simplificando, la API es la misma que en el caso de has_many

Las reglas para guardar los objetos en la base de datos tambiénson las mismasAsí que vamos a aplicar el principio DRY ;)

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 27 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 28 / 64

Usando la API de consultas

artist = Artist.find_by_name(’B.B. King’)artist.albums.where("year < 2000")

Simplificando, se traduce en:

SELECT * FROM "artists" LEFT OUTER JOIN "albums"ON "albums"."artist_id" = "artists"."id"WHERE (albums.year < 2000)

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 29 / 64

Eager-loadingn + 1 consultas

albums = Album.limit(10)albums.each do |album|puts "#{album.artist.name}: #{album.title}"

end

Esto dispararía 1 consulta para recuperar los álbums. . .. . . y otra por cada album para recuperar su artista¡En total, 101 consultas!

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 30 / 64

Eager-loadingDe n + 1 a tan sólo 2

albums = Album.includes(:artist).limit(10)

Esto dispara sólo 2 consultas:I Una para los álbumsI Y otra para todos los artistas relacionados

SELECT albums.* FROM albums LIMIT 10SELECT artists.* FROM artists WHEREWHERE (albums.artist_id IN (1, 2, 5))

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 31 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 32 / 64

Dependencias entre objetos

A veces la existencia de un objeto depende de otroSi por ejemplo borramos un artista, nos interesa borrar sus discos

class Artisthas_many :albums, :dependent => :destroy

end

u2 = Artist.find_by_name(’U2’)u2.destroy # Elimina a U2 y todos sus álbums

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 33 / 64

Tipos de dependencia

destroy Llama a destroy para cada uno de los objetosasociados

delete/delete_all Borra los objetos asociados pero sin llamar adestroy

nullify Pone la clave ajena a nullrestrict No permite borrar el objeto si hay otro asociado

Se usan principalmente con has_many y has_oneDebe evitarse su uso en belongs_to por la posibilidad de dejarobjetos "huérfanos"

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 34 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 35 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 36 / 64

No siempre es posible

Seguir las convenciones permite escribir menos código. . .pero no siempre es posibleAfortunadamente, ActiveRecord ofrece un buen número demodificadores

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 37 / 64

Ignorando las convenciones

class Log < ActiveRecord::Basehas_many :log_entries

end

class LogEntry < ActiveRecord::Basebelongs_to :log

end

log.log_entries # No parece muy bonito

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 38 / 64

Ignorando las convenciones

class Log < ActiveRecord::Basehas_many :entries, :class_name => "LogEntry"

end

class LogEntry < ActiveRecord::Basebelongs_to :log

end

log.entries # Mejor :)

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 39 / 64

Ignorando las convenciones

class Log < ActiveRecord::Basehas_many :entries, :class_name => "LogEntry",:foreign_key => "l_id"

end

class LogEntry < ActiveRecord::Basebelongs_to :log, :foreign_key => "l_id"

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 40 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 41 / 64

Ordenación

Permite ordenar los objetos dentro de la relación

class Artist < ActiveRecord::Basehas_many :albums, :order => :year

end

queen = Artist.find_by_name("Queen")queen.albums.map(&:year) # [ 1973, 1974, 1974, ... ]

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 42 / 64

Sentido de la ordenación

class Artist < ActiveRecord::Basehas_many :albums, :order => "year desc"

end

queen = Artist.find_by_name("Queen")queen.albums.map(&:year) # [ 1995, 1991, 1989, ... ]

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 43 / 64

Ordenación compuesta

class Artist < ActiveRecord::Basehas_many :albums, :order => "year asc, title desc"

end

queen = Artist.find_by_name("Queen")queen.albums.map(&:title)# [ "Queen", "Sheer heart attack", "Queen II", ... ]

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 44 / 64

Condiciones

Permite filtrar la relación con condiciones

class Artist < ActiveRecord::Basehas_many :albumshas_many :greatest_albums, :class_name => "Album",

:conditions => { :rate => [ 4, 5 ] }end

queen = Artist.find_by_name("Queen")queen.greatest_albums.first

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 45 / 64

Límites

Limita la cantidad de objetos devueltos

class Artist < ActiveRecord::Basehas_many :albums, :order => :yearhas_many :latest_albums, :class_name => "Album",

:limit => 2, :order => "year desc"end

queen = Artist.find_by_name("Queen")queen.latest_albums.map(&:year) # [ 1995, 1991 ]

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 46 / 64

EjercicioAñadiendo árbitros a Bet on Rails

1 Queremos que los usuarios de Bet on Rails sepan quién pita cadapartido

2 Añadir a Bet on Rails un modelo Referee que represente a losárbitros

3 Interesan su nombre y su fecha de nacimiento4 Implementar una gestión básica usando el "scaffold"5 Hacer que para cada partido se pueda seleccionar un árbitro

(pista: collection_select)6 ¿Cómo podría acceder a los partidos ya pitados por un árbitro?

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 47 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 48 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 49 / 64

Algo con dirección

class Address < ActiveRecord::Basebelongs_to :addressable, :polymorphic => true

end

class Company < ActiveRecord::Basehas_many :addresses, :as => :addressable

end

class Person < ActiveRecord::Basehas_one :address, :as => :addressable

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 50 / 64

¿Dónde está el truco?

Además de la columna _id, se usa una columna _type

En esa columna se guarda la clase del objeto asociado

address = Address.find_by_postal_code("35017")address.addressable_id # 1address.addressable_type # "Company"

En la migración hay que indicar que se trata de una relaciónpolimórfica

t.references :addressable, :polymorphic => true

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 51 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 52 / 64

¿Para qué?

Nos permite asociar dos modelos a través de un terceroUsos típicos:

1 Para añadir "lógica" a una asociación HABTM2 Como "atajo" en asociaciones has_many anidadas

Se verá más claro con dos ejemplos

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 53 / 64

Join models

Supongamos una asociación HABTM a la que queremos añadirlógica (atributos, validaciones, etc.)

class User < ActiveRecord::Basehas_and_belongs_to_many :groups

end

class Group < ActiveRecord::Basehas_and_belongs_to_many :users

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 54 / 64

Join models

Puede sustituirse por un modelo intermedio con dos relacionesuno a muchos

class User < ActiveRecord::Basehas_many :subscriptions

end

class Group < ActiveRecord::Basehas_many :subscriptions

end

class Subscription < ActiveRecord::Basebelongs_to :userbelongs_to :group

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 55 / 64

Join models

create_table :subscriptions do |t|t.references :usert.references :groupt.boolean :activet.timestamps

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 56 / 64

Join models

Así se puede llegar de un extremo al otro:

class User < ActiveRecord::Basehas_many :subscriptionshas_many :groups, :through => :subscriptions

end

class Group < ActiveRecord::Basehas_many :subscriptionshas_many :users, :through => :subscriptions

end

class Subscription < ActiveRecord::Basebelongs_to :userbelongs_to :group

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 57 / 64

Como si fuera HABTM

Se pueden usar los métodos habituales entre los extremosSe crearán "automáticamente" nuevos objetos intermediossiempre que sea necesarioCuando se eliminen, no se llamará a "destroy"

lanzarote = User.find_by_name("Lanzarote")lanzarote.groups.empty? # truelanzarote.subscriptions.empty? # trueknights = Group.find_by_name("Knights")lanzarote.groups << knightslanzarote.subscriptions.empty? # false

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 58 / 64

has_many anidados

class Document < ActiveRecord::Basehas_many :pages

end

class Page < ActiveRecord::Basebelongs_to :documenthas_many :paragraphs

end

class Paragraph < ActiveRecord::Basebelongs_to :page

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 59 / 64

has_many anidados

class Document < ActiveRecord::Basehas_many :pageshas_many :paragraphs, :through => :pages

end

class Page < ActiveRecord::Basebelongs_to :documenthas_many :paragraphs

end

class Paragraph < ActiveRecord::Basebelongs_to :page

end

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 60 / 64

Contenidos1 Asociaciones: lo básico

¿Qué son?Uno a unoUno a muchosMuchos a muchosAsociaciones y consultasDependencias

2 Asociaciones: opciones destacadasIgnorando las convencionesOrdenación y límites

3 Asociaciones avanzadasPolimórficashas_many :through

4 Herencia

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 61 / 64

Single Table Inheritance (STI)Todos los campos —de la clase base y las derivadas— en unatablaEl tipo concreto se almacena en la columna “type”Se puede pasar la opción --parent al generador

File

-path: string-size: integer

Text

-lines: string-words: integer

Binary

-format: string

filespath stringsize stringlines integerwords integerformat stringtype string

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 62 / 64

Ejercicio 1Modelando una plataforma de e-learning

Queremos escribir una plataforma de e-learningEn una primera versión, tenemos cursos, temas y tareas

I Cada curso tiene una serie de temas y tareas asociadasI Además, los temas y las tareas tienen asociados una serie de

documentos

Nuestros usuarios serán profesores y estudiantesUn curso puede tener varios profesores asignadosUn estudiante puede matricularse en cualquier curso

I Nos interesa saber cuándo formalizó la matrículaI Y también nos gustaría poder desactivarla en un momento dado

Implementarlo a nivel de modelos, olvidando la interfaz web

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 63 / 64

Ejercicio 2Modelando los equipos para Bet on Rails

1 Añadir a Bet on Rails un modelo Team que representa a losequipos e implementar una gestión básica (con el "scaffold")

2 La clase Game dejará de usar cadenas para representar a losequipos y usará esa nueva clase

3 Al crear/editar mediante el navegador deben seleccionarse losequipos de los registrados en la base de datos (pista:collection_select)

4 ¿Cómo podría acceder a los partidos que un equipo ha jugado encasa?

Áncor/Imobach GS (Banot.net) Desarrollo web con Ruby on Rails 3 Octubre de 2010 64 / 64