conceptos-dsls-domainspecificlanguage-dsl---rails
Ruby & Rails
Vemos un poco de ruby on rails. Generamos el scaffold para una nueva entidad, y vemos un poco el código generado para especificar la DB, específicamente la especificación de la creación de la tabla. Llamados objetos Migrators.
class `CreatePosts < ActiveRecord::Migration`
`def` `self``.up`
`create_**table**:**posts `do` `|t|`
`t.string:**name
`t.string:**title
`t.text:**content
`t.**timestamps
`end`
`end`
`def` `self``.down`
`drop_table:posts`
`end`
end
Es UN DSL!
Luego vemos las entidades de dominio generadas.
class `**Post** < ActiveRecord::Base`
`**validates**:**name`, :**presence `=>true`
`validates:**title`,:presence` `=>true``,`
`:**length `=> {:**minimum** `=>5`** `}`
end
Vemos acá un par de cosas:
- “validates” es un método de clase, heredado de ActiveRecord
- sin embargo, con el juego de la sintaxis parecería una sentecia declarativa del estilo “validar que la longitud de title sea como mínimo 5”
- es código ruby normal, solo que estos métodos son parte del “paquete” rails.
estas declaraciones involucran comportamiento y complejidades que quedan “ocultas” tras esos métodos. Por ejemplo,
- validaciones a nivel de pantalla en la ui.
- validaciones a nivel de persistencia de las entiedades (title length >= 5)
Ejemplo de uso:
>> p = **Post.new**(:content => "A new post")
=> #<Post id: nil, name: nil, title: nil,
`content: "A new post", created_at: nil,`
`updated_at: nil>`
>> **p.save**
=> false
>> p.**errors**
=> #<OrderedHash { :**title**=>[**"can't be blank"**,
`**"is too short (minimum is 5 characters)"**],`
`:**name**=>[**"can't be blank"**] }>
Vemos ahora las asociaciones entre los modelos, es decir, las "relaciones"
class**Post < ActiveRecord::Base
has_many:comments
end
class `**Comment** < ActiveRecord::Base`
`**belongs_to**:**post
end
Post has_many :comments
hace varias cosas a través de metaprogramación, gracias a que es dinámico (o son checkeos en tiempo de compilación), y tiene bloques…
- agrega dos variables a Post y a Comment
- genera código para mantener sincronizadas las properties.
- agrega ciertas otras reglas de acuerdo a la relacion (por ejemplo si es una agregación)
- utiliza inferencia sobre el nombre “comments” para traducir a singular y buscar el nombre de la clase “Comment”
- etc.
a pesar de hacer todo esto,
- nosotros no lo vemos
- ni lo hacemos manualmente.
sin embargo, mantiene la declaratividad (has many comments), y “esconde” las complejidades del modelo subyacente (validaciones, creación de los scripts de db, etc).