Ultimamente el desarrollo en Ruby/Rails me ha hecho pensar en el código de una manera anormal, cada vez mucho mas obstinado en los principios de DRY y KISS me quedo hasta horas analizando mis implementaciones y trato de que las mismas sean lo mas Ruby posible.

Para los que programan en Rails, muchos tendrán claro el funcionamiento de los métodos has_many o belongs_to, para los no tan expertos, es posible pasarle un bloque y definir métodos especiales para esa relación, con esto se puede lograr unos "syntatic sugar" bastante chéveres.

Por ejemplo asumiendo que tienes el típico ejemplo de User y Articles

class Article < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :articles do
    def in_date_range(start_date, end_date)
         #Codigo de busqueda aqui...
    end
  end
end

Luego una vez obtenida una instancia de usuario, pudieramos ubicar sus articulos en un intervalo de tiempo de una manera sencilla y elegante

user = User.find(1)
user.articles.in_date_range(params[:start_date], params[:end_date])

Ahora bien, cuando agregamos otro modelo a esta mezcla las cosas se ponen más interesantes. Vamos a asumir que tenemos un modelo Newspaper que también tiene muchos articles y además estos se van a pedir en un intervalo de tiempo. ¿Que hacemos? fácil, copia y pega el código de User y listo ya tienes el problema resuelto.

class Newspaper < ActiveRecord::Base
  has_many :users
  has_many :articles do
    def in_date_range(start_date, end_date)
         #Codigo de busqueda aqui...
    end
  end
end

class User < ActiveRecord::Base
  belongs_to :newspaper
  has_many :articles
end

class Article < ActiveRecord::Base
  belongs_to :user
  belongs_to :newspaper
end

Claro, esto no es DRY, si por casualidad tenemos otros modelos que tengan muchos articles, y por mala suerta se tenga que cambiar el código esto proceso se va a convertir en una agonía extrema.

Entre tanta pensadera se me ocurrio una brillante idea, (pensando para mi mismo te la comiste!) ¿Que tal si creamos un modulo en la carpeta de lib del proyecto y lo incluimos dentro del bloque que abrimos en el has_many? Algo así como

#lib/date_query_extension.rb
module DateQueryExtension
  def in_date_range(start_date, end_date)
    # codigo aqui
  end
end

# en los modelos
has_many :articles { include DateQueryExtension }

Mucho mejor!, ahora cada vez que queramos cambiar el codigo de in_date_range, ya solo tenemos que hacerlo una vez y no en cada relacion has_many :articles.

Claro el detalle es que cuando veo la documentacion de ActiveRecord::Base, me doy cuenta de que la gente de Rails ya habia pensado en esto, y no sólo eso, sino que también te ofrecen en los métodos del módulo la información de la relación (tablas que se relacionan, foreign keys, etc) y también las intancias del objeto padre y los objetos hijos. Increible, fue la sensación de que equivocado estaba al pensar que a mi sólo se me habia ocurrido la cuestión. Rails ya lo tenía integrado en su framework, al final el código queda de la siguiente forma

has_many :articles, :extend => DateQueryExtension

Al ver esta clase de cosas, pienso lo genial que es Rails y cómo este te hace recordar lo "pequeño saltamontes" que eres :-).


0 Respuestas a “Algunas veces me sorprendo de mi mismo, luego Rails me sorprende mucho mas...”

  1. Ningún Comentario

Añade un Comentario





RSS feeds

Suscríbete a nuestros RSS Feeds