2012-07-27 14 views
8

Sono un principiante di rails e sto cercando di eseguire una ricerca su un tavolo con binari, e sto solo usando la mia conoscenza sql per farlo. Ma questo non sembra nemmeno rotaie o rubino ...Come aggiungere clausole condizionali dove nelle rotaie

C'è un modo migliore per fare quello che sto facendo qui sotto? (Sostanzialmente, passare solo argomenti data sql se sono riempite)

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 

EDIT

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 

contenitore. rb

belongs_to :label 
belongs_to :place 
belongs_to :user 

label.rb

belongs_to :user 
has_many :containers 

Fondamentalmente, voglio ottenere un conteggio del numero di contenitori all'interno di etichette di un dato utente o con un rapporto diretto, per ogni posizione, e vogliono essere in grado di filtrare per data di inizio e fine.

Una di queste date può essere nulla, e quindi avrei bisogno di affrontare questo nella mia "query".

La mia domanda è: come posso fare questo il modo rotaie? Ho dato un'occhiata a http://guides.rubyonrails.org/active_record_querying.html e forse potrei usare il comando except qui da qualche parte ... ma questo modello di relazione sembra un po 'complesso farlo con ActiveRecord ... come posso ?, penso davvero che dovrei usare ActiveRecord, ma Come?

Grazie

+0

[qui è un buon esempio di come fare si unisce con record attivo] [1] [1]: http://stackoverflow.com/questions/764538/ruby-on-rails-how -a-join-two-tables –

+0

Ciao, il mio problema non è con i join ... Io non li ho scritti perché non sono rilevanti.La mia cosa è con i parametri di ricerca condizionale – MrWater

+0

@itsalltime - Penso che quello che Bob sta cercando di dire è - perché non usare Active Record invece di scrivere SQL straight-up? http://guides.rubyonrails.org/active_record_querying.html – JasCav

risposta

18

È possibile applicare più where chiamate a una query in modo da poter creare una query di base:

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

e quindi aggiungere un altro where chiamata a seconda del l'intervallo di date:

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 

Ogni chiamata where aggiunge un altro elemento alla clausola WHERE generale che utilizza AND, ad esempio:

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

è lo stesso che dire WHERE a AND b AND c.

+0

Ciao, questa risposta è ottima. Grazie. Sembra che non possa usare il begin_date .. end_date (e ho dovuto usare blank? Invece di nil), perché sto raccogliendo i datetimes dal campo di testo e convertendoli localmente. 'if! begin_date.blank? begin_date = DateTime.strptime ("# {begin_date} 00:00:00", "% m /% d /% Y% H:% M:% S"). To_datetime fine' Ho finito per utilizzare il tuo suggerimento alternativo : 'o where ('created_at between: begin_date e: end_date',: begin_date => begin_date,: end_date => end_date)' – MrWater

+0

@itsalltime: Utilizzare 'begin_date .. end_date' dovrebbe funzionare se' begin_date' e 'end_date' sono oggetti con date reali, ma sembra che tu abbia effettivamente delle stringhe. Ti consiglio di convertirli in oggetti data prima di utilizzarli in modo che ti preoccupi solo dei problemi relativi al formato della data in un unico punto. –

+0

Salve, li converto con la funzione pubblicata sopra, ma anche così il begin_date .. end_date non funziona, ed è per questo che dovevo andare per l'alternativa – MrWater

0

Non riesco a pensare a un grande motivo per cui si sarebbe effettivamente desidera generare SQL nel codice. La registrazione attiva sembra una soluzione molto più efficiente per le tue esigenze, a meno che non vi sia una ragione per cui non puoi utilizzarla.

Link explaining how to join tables with active record

+0

In realtà avevo qualche dubbio su come utilizzare i join, ma credo di aver trovato un modo per rispondere a ciò che volevo, come ho postato nella mia risposta modificata. La mia cosa è in realtà con i parametri di ricerca condizionale. – MrWater

+0

oh, per casi come questo e altre cose: http://www.rigelgroupllc.com/blog/2014/09/14/working-with-complex-sql-statements/ – Danny