2012-07-27 11 views
8

Soy un novato en los rieles y estoy tratando de realizar una búsqueda sobre una mesa con rieles, y solo estoy usando mi conocimiento SQL para hacerlo. Pero esto simplemente no parece carriles o ruby, incluso ...Cómo agregar cláusulas condicionales donde en los rieles

¿Hay alguna otra forma mejor de hacer lo que hago a continuación? (Básicamente, sólo pasan argumentos de fecha a SQL si se surten)

def search(begin_date=nil, end_date=nil) 

    subject = " and created_at " 

    if !(begin_date.nil? || end_date.nil?) 
     where_part = subject + "BETWEEN :begin_date AND :end_date" 
    else if (begin_date.nil? && end_date.nil?) 
     where_part = "" 
    else if(begin_date.nil?) 
     where_part = subject + " <= :end_date" 
    else if (end_date.nil?) 
     where_part = subject + " >= :begin_date" 
    end 
    end 
    end 
    end 

    User.joins(places: {containers: {label: :user}}).where("users.id= :user_id "+where_part, user_id: self.id, begin_date:begin_date, end_date:end_date).group(...).select(...) 
end 

EDITAR

user.rb

has_many :containers 
has_many :user_places 
has_many :places, through: :user_places 
has_many :labels 

place.rb

has_many :containers 
has_many :user_places 
has_many :users, through: :user_places 

contenedor. rb

belongs_to :label 
belongs_to :place 
belongs_to :user 

label.rb

belongs_to :user 
has_many :containers 

Básicamente, quiero obtener un recuento del número de contenedores dentro de las etiquetas de un usuario determinado o con una relación directa, por ubicación, y quieren ser capaces de filtrarla por las fechas de inicio y finalización.

Cualquiera de estas fechas puede ser nula, por lo que tendré que abordar esto en mi "consulta".

Mi pregunta es: ¿Cómo puedo hacer esto al estilo de los rieles? Eché un vistazo a http://guides.rubyonrails.org/active_record_querying.html y quizás podría usar el comando except aquí en alguna parte ... pero este modelo de relación parece un poco complejo para hacer esto con ActiveRecord ... ¿cómo puedo ?, realmente creo que debería usar ActiveRecord, pero ¿cómo?

Gracias

+0

[aquí es un buen ejemplo de cómo hacerlo se une con el registro activo] [1] [1]: http://stackoverflow.com/questions/764538/ruby-on-rails-how -to-join-two-tables –

+0

Hola, mi problema no está en las uniones ... Simplemente no las escribí porque no son relevantes.Lo que pasa es que con los parámetros de búsqueda condicional – MrWater

+0

@itsalltime - Creo que lo que Bob intenta decir es - ¿por qué no usar Active Record en lugar de escribir SQL directamente? http://guides.rubyonrails.org/active_record_querying.html – JasCav

Respuesta

18

Se pueden aplicar varios where llamadas a una consulta para que pueda construir su consulta base:

query = User.joins(...) 
      .group(...) 
      .select(...) 
      .where('users.id = :user_id', :user_id => self.id) 

y luego añadir otro where llamada dependiendo de su intervalo de la fecha:

if(begin_date && end_date) 
    query = query.where(:created_at => begin_date .. end_date) 
    # or where('created_at between :begin_date and :end_date', :begin_date => begin_date, :end_date => end_date) 
elsif(begin_date) 
    query = query.where('created_at >= :begin_date', :begin_date => begin_date) 
elsif(end_date) 
    query = query.where('created_at <= :end_date', :end_date => end_date) 
end 

Cada llamada a where agrega otra pieza a su cláusula WHERE general utilizando Y así algo así como:

q = M.where(a).where(b).where(c) 

es lo mismo que decir WHERE a AND b AND c.

+0

Hola, esta respuesta es genial. Gracias. Parece que no puedo usar el begin_date .. end_date (y tuve que usar blank? En lugar de nil), porque estoy recopilando las fechas del campo de texto y las estoy convirtiendo localmente. 'if! begin_date.blank? begin_date = DateTime.strptime ("# {begin_date} 00:00:00", "% m /% d /% Y% H:% M:% S"). To_datetime end' Terminé usando su sugerencia alternativa : 'o donde ('created_at entre: begin_date y: end_date',: begin_date => begin_date,: end_date => end_date)' – MrWater

+0

@itsalltime: Usar 'begin_date .. end_date' debería funcionar si' begin_date' y 'end_date' son objetos de fecha real, pero parece que en realidad tienes cadenas. Recomiendo convertirlos a objetos de fecha antes de usarlos para que solo tenga que preocuparse por los problemas de formato de fecha en un solo lugar. –

+0

Hola, los convierto con la función publicada arriba, pero aun así el begin_date ... end_date no funciona, y es por eso que tuve que buscar la alternativa – MrWater

0

No puedo pensar en una gran razón por la que usted realmente desee generar SQL en el código. El registro activo parece ser una solución mucho más eficiente para sus necesidades, a menos que haya una razón por la que no pueda usar eso.

Link explaining how to join tables with active record

+0

De hecho, tenía algunas dudas sobre cómo usar las uniones, pero supongo que encontré una forma de abordar lo que quería, como publiqué en mi respuesta editada. Mi cosa es en realidad con los parámetros de búsqueda condicional. – MrWater

+0

oh, para casos como este y esas cosas: http://www.rigelgroupllc.com/blog/2014/09/14/working-with-complex-sql-statements/ – Danny

Cuestiones relacionadas