2009-07-07 3 views
7

Abbastanza sicuro che mi manca qualcosa di veramente semplice qui:Utilizzando will_paginate con più modelli (rotaie)

Sto cercando di visualizzare una serie di pagine che contengono le istanze di due diversi modelli - Profili e gruppi. Ho bisogno che ordinino con il loro attributo nome. Potrei selezionare tutte le istanze per ogni modello, quindi ordinare e impaginare, ma questo risulta sciatto e inefficiente.

Sto usando mislav-will_paginate e mi chiedevo se c'è un modo migliore per raggiungere questo obiettivo? Qualcosa del tipo:

[Profile, Group].paginate(...) 

sarebbe l'ideale!

risposta

6

Buona domanda, ho incontrato lo stesso problema un paio di volte. Ogni volta, ho finito scrivendo la mia query sql basata su unioni SQL (funziona bene con sqlite e mysql). Quindi, è possibile utilizzare impaginare passando i risultati (http://www.pathf.com/blogs/2008/06/how-to-use-will_paginate-with-non-activerecord-collectionarray/). Non dimenticare di eseguire la query per contare tutte le righe.

Alcune righe di codice (non testato)

my_query = "(select posts.title from posts) UNIONS (select profiles.name from profiles)" 
total_entries = ActiveRecord::Base.connection.execute("select count(*) as count from (#{my_query})").first['count'].to_i 

results = ActiveRecord::Base.connection.select_rows("select * from (#{my_query}) limit #{limit} offset #{offset}") 

E 'overkilled? Forse, ma hai il numero minimo di query e i risultati sono coerenti.

Spero che aiuti.

Nota: Se si ottiene il valore di offset da un param http, si dovrebbe usare sanitize_sql_for_conditions (vale a dire: SQL Injection ....)

0

Hai provato a visualizzare due diversi set di risultati con i rispettivi impaginatori e li aggiorna tramite AJAX? Non è esattamente quello che vuoi, ma il risultato è simile.

+0

Sfortunatamente questo non lo taglierà - Ho bisogno di avere le due serie di istanze insieme. – Codebeef

1

È possibile avvicinarsi fare qualcosa di simile:

@profiles, @groups = [Profile, Group].map do |clazz| 
    clazz.paginate(:page => params[clazz.to_s.downcase + "_page"], :order => 'name') 
end 

che poi impaginare utilizzando i parametri di pagina profile_page e group_page. È possibile ottenere la chiamata will_paginate nella vista per utilizzare la pagina corretta utilizzando:

<%= will_paginate @profiles, :page_param => 'profile_page' %> 
.... 
<%= will_paginate @groups, :page_param => 'group_page' %> 

Eppure, io non sono sicuro che ci sia un enorme vantaggio rispetto la creazione @groups e @profiles singolarmente.

1

nel mio ultimo progetto ho bloccato in un problema, ho dovuto impaginare multipla modelli con paginazione singola nella mia funzionalità di ricerca. dovrebbe funzionare in modo che il primo modello debba apparire per primo quando i risultati del primo modello un secondo modello dovrebbero continuare i risultati e il terzo e così via come un singolo feed di ricerca, proprio come i feed di Facebook. questa è la funzione che ho creato per fare questa funzionalità

def multi_paginate(models, page, per_page) 

    WillPaginate::Collection.create(page, per_page) do |pager| 

    # set total entries 
    pager.total_entries = 0 
    counts = [0] 
    offsets = [] 
    for model in models 
      pager.total_entries += model.count 
      counts << model.count 
      offset = pager.offset-(offsets[-1] || 0) 
      offset = offset>model.count ? model.count : offset 
      offsets << (offset<0 ? 0 : offset) 
    end 

    result = [] 
    for i in 0...models.count 
      result += models[i].limit(pager.per_page-result.length).offset(offsets[i]).to_a 
    end 

    pager.replace(result) 
    end 

end 

Provatelo e fatemi sapere se avete qualche problema con esso, ho anche postato come un problema da will_paginate repository, se tutti confermato che funziona correttamente lo forzo e lo affido alla biblioteca. https://github.com/mislav/will_paginate/issues/351