2010-12-04 55 views
66

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

Por ejemplo, en mi sitio tengo una sección de opinión donde los usuarios pueden calificar las opiniones. Aquí es un método que escribí para reunir los usuarios que han clasificado 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

+1

Viniendo desde una búsqueda en Google de "rails paginate array", quería compartir con otros visitantes que [kaminari] (https://github.com/amatsuda/kaminari) es la alternativa de paginación de rieles que establecí en . Maneja matrices elegantemente. –

Respuesta

201

will_paginate 3.0 está diseñado para aprovechar el nuevo ActiveRecord::Relation en 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 rieles que requieran esa parte.

En un archivo en su config/initializers (utilicé will_paginate_array_fix.rb), añadir este

require 'will_paginate/array' 

continuación, puede utilizar en matrices

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

¡Thx! funcionó como un amuleto – ajbraus

+0

Disculpa por la respuesta de unos años más tarde. ¡Esto fue útil hoy! Lo aprecio – Brian

+0

Esto ayudó, pero no muestra la paginación en la vista correctamente. –

9

usted podría utilizar Array#from para simular la paginación, pero el verdadero problema aquí es que no se debe utilizar Array en absoluto.

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

Te voy a enseñar una manera mejor de hacer la misma cosa:

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 el esquema de base de datos está siguiendo las convenciones de nombres propios o de todo esto va a romper. Asegúrese de crear las tablas con Database Migrations en lugar de hacerlo a mano.

Estas asociaciones crearán ayudantes en sus modelos para facilitar la búsqueda. En lugar de repetir una lista de OpinionRatings y recopilar 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 cualquiera de los casos se puede llamar for(id) en el modelo OpinionRatings y pasarlo un id:

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 se puede paginar fácilmente:

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

Actualización para Rieles 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 los nuevos carriles mi preferencia es kaminari de paginación:

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

Bueno, las asociaciones son tabla Opinion has_many: opinion_ratings, y belongs_to: opinion. A la tabla de perfiles le gusta una opinión a través de una relación de muchos a muchos con una tabla de unión llamada Categorías. Con esta configuración, ¿sabes cómo cambiaría el código que mencionaste anteriormente? – Brian

+0

@Brian He actualizado mi ejemplo, pero no puedo estar seguro a menos que me muestres tus clases modelo. –

+0

Adam, ¿cómo obtengo el modelo de evaluación de opinión? Si estoy entendiendo bien, ¿Profile.with_opinion devuelve una lista de todos los perfiles con el ID especificado? Lo que necesito es obtener una lista de perfiles del modelo OpinionRating, que pertenece a: opinion y Opinion has_ ​​many: opinion_ratings. El modelo de perfil está vinculado al modelo de opinión a través de la tabla de combinación de Categorías. – Brian

4

La gema will_paginate paginará tanto las consultas como las matrices de ActiveRecord.

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

que se aprovecharon de las asociaciones de los carriles, y se acercó con 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 de este modo:

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

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

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

Eso parecía lo mismo que usar el método de encontrar, aunque.

Gracias por la ayuda.

0

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

Instalación will_paginate:

joya instalan will_paginate

Añadir a Gemfile y ejecutar bundle.

controlador módulo de

class DashboardController < ApplicationController 
    include StructHelper 

    def show 
     @myData =structHelperGet.paginate(:page => params[:page]) 
    end 

end 

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 rieles.

Ver

<div id="Data"> 
       <%= will_paginate @myData%> 
        <table> 
        <thead> 
        <tr> 
        <th>col 1</th> 
        <th>Col 2</th> 
        <th>Col 3</th> 
        <th>Col 4</th> 
        </tr> 
        </thead> 
        </tbody> 
        <% @myData.each do |app| %> 
         <tr> 
          <td><%=app[:col1]%> </td> 
          <td><%=app[:col2]%> </td> 
          <td><%=app[:col3]%> </td> 
          <td><%=app[:col4]%> </td> 
         </tr> 

        <% end %> 
        </tbody> 
        </table> 
       <%= will_paginate @myData%> 
       </div> 

Esto le dará pagnation de los predeterminados de 30 filas por página.

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

1

Si no desea utilizar el archivo de configuración o Si 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 el punto de vista de base de datos, pero es una opción para que nadie tenga problemas con el archivo de configuración will_paginate.