Forum: Rails-ES evaluar condiciones dinámicas

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Eduardo Fernandez Corrales (Guest)
on 2007-05-03 17:12
(Received via mailing list)
Hola,

Tengo una aplicación en la cual necesito obtener siempre los objetos
en base a una condición dinámica, algo como esto:

class Recinto < ActiveRecord::Base
  has_many :sesiones, :conditions => [fecha > ?, Time.now]
  has_many :espectaulos, :through => sesiones
end

El problema de hacerlo así es que la condición se fija en el momento
de carga de la clase y luego no se vuelve a evaluar.

He estado mirando la opción with_scope, así como algunos plugins que
la usan pero siempre me encuentro con el mismo problema con las
condiciones dinámicas.

Supongo que siempre queda la alternativa de hacer un before_filter,
evaluar la condición y pasarla, pero me parece farragoso.

¿Cual sería la forma más DRY de hacer ésto?

Gracias y saludos.
Sergio Gil Pérez de la Manga (Guest)
on 2007-05-03 17:41
(Received via mailing list)
On 5/3/07, Eduardo Fernandez Corrales <eduardo.fernandez@gmail.com>
wrote:
> El problema de hacerlo así es que la condición se fija en el momento
> de carga de la clase y luego no se vuelve a evaluar.
>
> He estado mirando la opción with_scope, así como algunos plugins que
> la usan pero siempre me encuentro con el mismo problema con las
> condiciones dinámicas.
>
> Supongo que siempre queda la alternativa de hacer un before_filter,
> evaluar la condición y pasarla, pero me parece farragoso.
>
> ¿Cual sería la forma más DRY de hacer ésto?

Yo haría algo
así:
 class Recinto < ActiveRecord::Base
   has_many :sesiones
   has_many :espectaulos, :through => :sesiones

  def sesiones_futuras
    sesiones.find(:all, :conditions => ["fecha > ?", Time.now])
  end
 end

También tendrías que hacer algo parecido para los espectáculos, claro.

--
Sergio Gil Pérez de la Manga
e-mail > sgilperez@gmail.com
blog > http://www.lacoctelera.com/porras
352a2aa00f25dea79560b959646c9d62?d=identicon&s=25 Damian J. (djanowski)
on 2007-05-03 18:42
(Received via mailing list)
On 5/3/07, Sergio Gil Pérez de la Manga <sgilperez@gmail.com> wrote:
> On 5/3/07, Eduardo Fernandez Corrales <eduardo.fernandez@gmail.com> wrote:
> > Hola,
> >
> > Tengo una aplicación en la cual necesito obtener siempre los objetos
> > en base a una condición dinámica, algo como esto:
> >
> > class Recinto < ActiveRecord::Base
> >   has_many :sesiones, :conditions => [fecha > ?, Time.now]
> >   has_many :espectaulos, :through => sesiones
> > end

Eduardo, qué pasa si hacés esto:

class Recinto < ActiveRecord::Base
  has_many :sesiones, :conditions => 'fecha > '#{Time.now.to_s(:db)}'
  has_many :espectaulos, :through => sesiones
end

Ojo, que las comillas son simples, justamente porque no querés que se
evalúe en la definición de la clase. Estoy casi seguro que una vez
anduvo...


Sergio, creo que lo que decís se podría hacer
así:
class Sesion < AR::Base
  class << self
    def futuras
      find(:all, :conditions => ["fecha > ?", Time.now])
    end
  end
end

class Recinto < AR::Base
  has_many :sesiones
end

y luego:

recinto = Recinto.find(:first)
recinto.sesiones.futuras

Perdón que no lo puedo probar ahora :(

Pero también estoy casi seguro de que anda y es lindo :)

Saludos!
Sergio Gil Pérez de la Manga (Guest)
on 2007-05-03 18:58
(Received via mailing list)
On 5/3/07, Damian Janowski <damian.janowski@gmail.com> wrote:
>   has_many :sesiones
> end
>
> y luego:
>
> recinto = Recinto.find(:first)
> recinto.sesiones.futuras
>
> Perdón que no lo puedo probar ahora :(
>
> Pero también estoy casi seguro de que anda y es lindo :)

Sí, o también (ojo que tampoco lo he probado ahora mismo para este
ejemplo concreto):

has_many :sesiones do
  def futuras
    find(:all, :conditions => ["fecha > ?", Time.now])
  end
end

y luego, igual:

recinto = Recinto.find(:first)
recinto.sesiones.futuras

La verdad es que hay varias formas de hacerlo y elegí la más fea =xD
En realidad todas vienen a ser lo mismo, y funcionan (deberían, vaya).

--
Sergio Gil Pérez de la Manga
e-mail > sgilperez@gmail.com
blog > http://www.lacoctelera.com/porras
Xavier Noria (Guest)
on 2007-05-03 19:08
(Received via mailing list)
On May 3, 2007, at 6:41 PM, Damian Janowski wrote:

>>>   has_many :espectaulos, :through => sesiones
>>> end
>
> Eduardo, qué pasa si hacés esto:
>
> class Recinto < ActiveRecord::Base
>   has_many :sesiones, :conditions => 'fecha > '#{Time.now.to_s(:db)}'


El problema de esta aproximacion es que esa linea invoca un metodo de
clase que se ejecuta al interpretar la definicion, por tanto una sola
vez en la vida de la clase.

Debido a ello, la definicion de la relacion se queda con ese valor
"cacheado" ya que se interpola la cadena al ejecutarse el metodo.
Esto en desarrollo puede que no se vea porque la clase se recarga por
request, pero en produccion no funcionaria.

-- fxn
Eduardo Fernandez Corrales (Guest)
on 2007-05-03 19:51
(Received via mailing list)
Damian,

Efectivamente Xavier tiene razón, son métodos de clase que se
mantienen durante la vida de la clase, con lo cual sigo teniendo el
problema.

El primer ejemplo que dio Sergio al ser un método de intancia sí
funciona, creo que es la mejor forma.

Gracias 1024.
352a2aa00f25dea79560b959646c9d62?d=identicon&s=25 Damian J. (djanowski)
on 2007-05-03 20:38
(Received via mailing list)
On 5/3/07, Xavier Noria <fxn@hashref.com> wrote:
> Esto en desarrollo puede que no se vea porque la clase se recarga por
> request, pero en produccion no funcionaria.

Xavier, justamente por eso puse las comillas simples, no las dobles.
Lo que me pasó es que lo probé una vez y me anduvo, como si el valor
de :conditions fuese evaluado al construir la consulta.

De todas maneras es un hack bastante feo :)
Xavier Noria (Guest)
on 2007-05-03 21:50
(Received via mailing list)
On May 3, 2007, at 8:37 PM, Damian Janowski wrote:

>> Debido a ello, la definicion de la relacion se queda con ese valor
>> "cacheado" ya que se interpola la cadena al ejecutarse el metodo.
>> Esto en desarrollo puede que no se vea porque la clase se recarga por
>> request, pero en produccion no funcionaria.
>
> Xavier, justamente por eso puse las comillas simples, no las dobles.
> Lo que me pasó es que lo probé una vez y me anduvo, como si el valor
> de :conditions fuese evaluado al construir la consulta.

Ah, ok, como en general la evaluacion de codigo con eval es inusual,
la cadena no estaba cerrada, y el SQL de dentro tenia comillas
simples, pense que la de afuera era en realidad doble.
This topic is locked and can not be replied to.