2013-03-07 18 views
6

Ad esempio, ho un evento con start_date e length (come numero intero che rappresenta giorni).Rails & Ransack - Ordinamento/ricerca basato su una definizione nel modello

Nel modello definisco end_date come start_date + length.days molto semplice come ci si aspetterebbe:

def end_date 
    start_date + length.days 
end 

Tutto funziona bene nel modello, posso usare event.end_date per visualizzare la data di inizio più però lunghezza molti giorni è stato impostato su , tuttavia, desidero ordinare gli eventi entro la data di fine utilizzando Ransack.

Il collegamento di ordinamento per start_date assomiglia a questo: <%= sort_link @q, :start_date, "Start" %>

Se provo lo stesso per END_DATE (<%= sort_link @q, :end_date, "End" %>) purtroppo in silenzio non riesce, come presumo che sta cercando end_date come una colonna nella tabella e non trovandola.

Sono semplicemente stupido o sto cercando di fare qualcosa che Ransack semplicemente non è stato creato?

+0

sembra che il ransack traduca i parametri di ricerca in query sull'ORM ActiveRecord - che fallirebbe sicuramente a meno che non si disponga di una colonna reale su cui il DB sottostante può cercare. – bdares

+0

Grazie per il commento @bdares. Ora sono riuscito a impostare 'ransacker: end do | r |' nel modello a questo: 'Arel :: Nodes :: SqlLiteral.new (" DATE_ADD (events.start_date, INTERVAL events.length DAY) ")'. Che produce la query: "SELECT DISTINCT events. * FROM events ORDER BY DATE_ADD (events.start_date, INTERVAL events.length DAY) DESC LIMIT 30 OFFSET 0'. Funziona, ma si sente orribilmente "hacky". – bensmithbwd

+0

@bensmithbwd - È difficile vedere la soluzione completa nel tuo commento. Abbi cura di scrivere un esempio completo in modo che possiamo ottenere una migliore comprensione della soluzione. Quindi puoi accettare la tua risposta. –

risposta

10

Proprio per il beneficio di tutti coloro che vogliono vedere come ho fatto:

Nel modello in cui ho definito data_finale

def end_date 
    start_date + length.days 
end 

Ho poi aggiunto un metodo 'ranksacker' di: END_DATE

ransacker :end_date do |r| 
    Arel::Nodes::SqlLiteral.new("DATE_ADD(`events`.`start_date`, INTERVAL `events`.`length` DAY)") 
end 

Sinceramente non so se questo è il modo migliore/giusto per fare la clausola sopra, ma ho molta più familiarità con SQL che con Ruby/Rails quindi ha funzionato per me essere così aperto.

: quello che fa in modo efficace è di creare un pezzo di SQL che ordina una query la stessa definizione data_finale (start_date + lunghezza)

posso ora nel template utilizzare il seguente codice per un collegamento sorta (che permette Ransacker per gestire l'ASC/DESC e non interferire con wil_paginate etc etc):

<%= sort_link @q, :end_date, "Event End Date" %>

Quando si sceglie quel link si otterrà una query sulla falsariga di:

SELECT DISTINCT events.* FROM events ORDER BY DATE_ADD(events.start_date, INTERVAL events.length DAY) DESC LIMIT 30 OFFSET 0 - Tutti creati e gestiti da Ransacker su una colonna della tabella che non esiste nemmeno!

Anche in questo caso, un rapido disclaimer, ho imparato Rails e Ruby per circa 2 settimane ora, provenienti da uno sfondo di PHP, quindi non sono in nessun modo un esperto e questo potrebbe essere orribilmente inefficiente o ci potrebbe essere molto meglio 'rotaie' di cui semplicemente non so nulla.