Ruby on Rails will_paginate una matriz

Me preguntaba si alguien podría explicar cómo usar will_paginate en una matriz de objetos.

Por ejemplo, en mi sitio tengo una sección de opinión donde los usuarios pueden calificar las opiniones. Aquí hay un método que escribí para reunir a los usuarios que han calificado la opinión:

def agree_list list = OpinionRating.find_all_by_opinion_id(params[:id]) @agree_list = [] list.each do |r| user = Profile.find(r.profile_id) @agree_list << user end end 

Gracias

will_paginate 3.0 está diseñado para aprovechar la nueva ActiveRecord::Relation in Rails 3, por lo que define paginate solo en las relaciones de forma predeterminada. Todavía puede funcionar con una matriz, pero debe indicarle a los Rails que requieran esa parte.

En un archivo en su config/initializers (utilicé will_paginate_array_fix.rb ), agregue esto

 require 'will_paginate/array' 

Entonces puedes usar en arreglos

 my_array.paginate(:page => x, :per_page => y) 

Puede usar Array#from para simular la paginación, pero el verdadero problema aquí es que no debería usar Array en absoluto.

Esto es para lo que están hechas las Asociaciones de ActiveRecord . Debes leer esa guía con cuidado, hay muchas cosas útiles que necesitarás saber si estás desarrollando aplicaciones de Rails.

Déjame mostrarte una mejor manera de hacer lo mismo:

 class Profile < ActiveRecord::Base has_many :opinion_ratings has_many :opinions, :through => :opinion_ratings end class Opinion < ActiveRecord::Base has_many :opinion_ratings end class OpinionRating < ActiveRecord::Base belongs_to :opinion belongs_to :profile end 

Es importante que su esquema de base de datos siga las convenciones de nomenclatura adecuadas o todo esto se romperá. Asegúrese de crear tablas con Migraciones de base de datos en lugar de hacerlo a mano.

Estas asociaciones crearán ayudantes en sus modelos para facilitar la búsqueda. En lugar de iterar una lista de OpinionRatings y recostackr los usuarios manualmente, puede hacer que Rails lo haga por usted con el uso de named_scope o scope dependiendo de si está utilizando Rails 2.3 o 3.0. Como no especificó, daré ambos ejemplos. Agregue esto a su clase OpinionRating:

2.3

 named_scope :for, lambda {|id| { :joins => :opinion, :conditions => { :opinion => { :id => id } } } } named_scope :agreed, :conditions => { :agree => true } named_scope :with_profiles, :includes => :profile 

3.0

 scope :agreed, where(:agree => true) def self.for(id) joins(:opinion).where(:opinion => { :id => id }) end 

En cualquier caso, puede solicitar for(id) en el modelo OpinionRatings y pasarle una identificación:

2.3

 @ratings = OpinionRating.agreed.for(params[:id]).with_profiles @profiles = @ratings.collect(&:profile) 

3.0

 @ratings = OpinionRating.agreed.for(params[:id]).includes(:profile) @profiles = @ratings.collect(&:profile) 

El resultado de todo esto es que ahora puedes paginar fácilmente:

 @ratings = @ratings.paginate(:page => params[:page]) 

Actualización para Rails 4.x: más o menos lo mismo:

 scope :agreed, ->{ where agreed: true } def self.for(id) joins(:opinion).where(opinion: { id: id }) end 

Aunque para Rails más nuevos, mi preferencia es kaminari para la paginación:

 @ratings = @ratings.page(params[:page]) 

La gem will_paginate tanto las consultas de ActiveRecord como las matrices.

 list = OpinionRating.where(:opinion_id => params[:id]).includes(:profile).paginate(:page => params[:page]) @agree_list = list.map(&:profile) 

Si no desea utilizar el archivo de configuración o tiene problemas con él, también puede asegurarse de devolver una relación ActiveRecord :: en lugar de una matriz. Por ejemplo, cambie el agree_list para que sea una lista de ID de usuario en su lugar, luego haga una IN en esos ID para devolver una relación.

 def agree_list list = OpinionRating.find_all_by_opinion_id(params[:id]) @agree_id_list = [] list.each do |r| user = Profile.find(r.profile_id) @agree_id_list << user.id end @agree_list = User.where(:id => @agree_id_list) end 

Esto es ineficiente desde la perspectiva de una base de datos, pero es una opción para cualquiera que tenga problemas con el archivo de configuración will_paginate.

Aproveché las asociaciones de Rails, y se me ocurrió un nuevo método:

 def agree_list o = Opinion.find(params[:id]) @agree_list = o.opinion_ratings(:conditions => {:agree => true}, :order => 'created_at DESC').paginate :page => params[:page] rescue ActiveRecord::RecordNotFound redirect_to(profile_opinion_path(session[:user])) end 

En mi opinión, busqué el perfil así:

 <% @agree_list.each do |rating| %> <% user = Profile.find(rating.profile_id) %> <% end %> 

Por favor, publique si hay una mejor manera de hacer esto. Traté de usar el helper named_scope en el modelo OpinionRating sin suerte. Aquí hay un ejemplo de lo que probé, pero no funciona:

 named_scope :with_profile, lambda {|id| { :joins => [:profile], :conditions => ['profile_id = ?', id] } } 

Sin embargo, eso parecía lo mismo que usar el método Find.

Gracias por toda la ayuda.

Estoy usando rails 3 ruby ​​1.9.2. Además, recién estoy comenzando la aplicación, por lo que no incluye css o estilos.

Instalar will_paginate:

joya instalar will_paginate

Agregar a Gemfile y ejecutar paquete.

Controlador

 class DashboardController < ApplicationController include StructHelper def show @myData =structHelperGet.paginate(:page => params[:page]) end end 

el módulo StructHelper consulta un servicio, no una base de datos. structHelperGet () devuelve una matriz de registros.

No estoy seguro si una solución más sofisticada sería falsificar un modelo, o tomar los datos de vez en cuando y volver a crear una tabla sqllite de vez en cuando y tener un modelo real para consultar. Solo estoy creando mi primera aplicación de Rails.

Ver

 
<%= will_paginate @myData%> <% @myData.each do |app| %> <% end %>
col 1 Col 2 Col 3 Col 4
<%=app[:col1]%> <%=app[:col2]%> <%=app[:col3]%> <%=app[:col4]%>
<%= will_paginate @myData%>

Esto le dará una paginación de las 30 filas predeterminadas por página.

Si aún no ha leído http://railstutorial.org , comience a leerlo ahora.