2009-07-07 5 views
7

ziemlich sicher, dass ich etwas wirklich einfach bin fehlt hier:Mit will_paginate mit mehreren Modellen (Rails)

Ich versuche, eine Reihe von Seiten anzuzeigen, die Fälle von zwei verschiedenen Modellen enthalten - Profile und Gruppen. Ich brauche sie mit ihrem Namensattribut. Ich könnte alle Instanzen für jedes Modell auswählen, sie dann sortieren und paginieren, aber das fühlt sich schlampig und ineffizient an.

Ich benutze mislav-will_paginate und frage mich, ob es einen besseren Weg gibt, dies zu erreichen? Etwas wie:

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

wäre ideal!

Antwort

6

Gute Frage, ich lief das gleiche Problem ein paar Mal. Jedes Mal beendete ich es, indem ich meine eigene SQL-Abfrage basierend auf sql unions schrieb (das funktioniert gut mit sqlite und mysql). Dann können Sie paginieren, indem Sie die Ergebnisse übergeben (http://www.pathf.com/blogs/2008/06/how-to-use-will_paginate-with-non-activerecord-collectionarray/). Vergessen Sie nicht, die Abfrage durchzuführen, um alle Zeilen zu zählen.

Einige Zeilen Code (nicht getestet)

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}") 

Ist es overkilled? Vielleicht, aber Sie haben die minimale Anzahl von Abfragen und die Ergebnisse sind konsistent.

Ich hoffe, es hilft.

Hinweis: Wenn Sie den Offset-Wert von einem http param erhalten, sollten Sie sanitize_sql_for_conditions verwenden (zB: SQL-Injection ....)

0

Haben Sie versucht, zwei verschiedene Ergebnissätze mit eigenen Paginatoren anzuzeigen und über AJAX zu aktualisieren? Es ist nicht genau das, was Sie wollen, aber das Ergebnis ist ähnlich.

+0

Leider wird das nicht schneiden - ich muss die beiden Sätze von Instanzen zusammen haben. – Codebeef

1

können Sie erhalten schließen etwas wie tun:

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

die dann Seite Parameter profile_page und group_page verwendet, wird Paginieren. Sie können den will_paginate Anruf in der Ansicht erhalten die richtige Seite zu verwenden, mit:

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

Aber ich bin nicht sicher, dass es ein großer Vorteil gegenüber @groups und @profiles individuell einrichten.

1

in meinem letzten Projekt, das ich in ein Problem stecken, musste ich Paginieren mehr Modelle mit einfacher Seitennummerierung in meiner Suchfunktion. sollte es so funktionieren, dass das erste Modell zuerst angezeigt wird, wenn die Ergebnisse des ersten Modells ein zweites Modell die Ergebnisse fortsetzen sollen und das dritte usw. als ein einziger Suchfeed, genau wie Facebook-Feeds. dies ist die Funktion i diese Funktionalität

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 

es zu tun erstellt versuchen, und lassen Sie mich wissen, wenn Sie ein Problem damit haben, ich habe es auch als ein Problem Repository will_paginate, wenn jeder bestätigte, dass es richtig funktioniert Ich verzweifle und übertrage es in die Bibliothek. https://github.com/mislav/will_paginate/issues/351