Ruby on Rails将_paginate一个数组

时间:2010-12-04 09:40:17

标签: ruby-on-rails pagination will-paginate

我想知道是否有人可以解释如何在一组对象上使用will_paginate

例如,在我的网站上,我有一个意见部分,用户可以对意见进行评分。这是我写的一个方法来收集评价意见的用户:

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

谢谢

7 个答案:

答案 0 :(得分:211)

will_paginate 3.0旨在利用Rails 3中的新ActiveRecord::Relation,因此默认情况下仅对关系定义paginate。它仍然可以使用数组,但你必须告诉rails要求该部分。

config/initializers(我使用will_paginate_array_fix.rb)的文件中,添加此

require 'will_paginate/array'

然后你可以在数组上使用

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

答案 1 :(得分:9)

您可以使用Array#from来模拟分页,但这里真正的问题是您根本不应该使用Array

这是 ActiveRecord Associations 的用途。您应该仔细阅读该指南,如果您正在开发Rails应用程序,则需要了解许多有用的内容。

让我告诉你一个更好的方法来做同样的事情:

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

重要的是,您的数据库架构遵循正确的命名约定或所有这些都将中断。确保您使用 Database Migrations 创建表格,而不是手动执行。

这些关联将在您的模型上创建帮助程序,以便更轻松地进行搜索。您可以使用named_scopescope使Rails为您执行此操作,而不是迭代OpinionRating列表并手动收集用户,具体取决于您使用的是Rails 2.3还是3.0。既然你没有指定,我会举两个例子。将其添加到您的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

在任何一种情况下,您都可以在for(id)模型上调用OpinionRatings并将其传递给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)

所有这一切的结果是你现在可以轻松地分页:

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

Rails 4.x的更新:或多或少相同:

scope :agreed, ->{ where agreed: true }

def self.for(id)
  joins(:opinion).where(opinion: { id: id })
end 

虽然对于较新的Rails,我的首选是kaminari分页:

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

答案 2 :(得分:4)

gem will_paginate将对ActiveRecord查询和数组进行分页。

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

答案 3 :(得分:1)

如果您不想使用配置文件或遇到问题,您还可以确保返回ActiveRecord :: Relation而不是数组。例如,将agree_list更改为用户ID列表,然后对这些ID执行IN以返回Relation。

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

从数据库角度来看,这是低效的,但对于任何遇到wi​​ll_paginate配置文件问题的人来说,它都是一个选项。

答案 4 :(得分:0)

我利用了rails关联,并提出了一种新方法:

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

在我看来,我像这样查看了个人资料:

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

如果有更好的方法,请发布。我试图在OpinionRating模型中使用named_scope助手而没有运气。这是我尝试过的一个例子,但不起作用:

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

这看起来和使用find方法一样。

感谢您的帮助。

答案 5 :(得分:0)

我正在使用rails 3 ruby​​ 1.9.2。另外,我刚刚开始使用应用程序,因此不包含css或样式。

安装will_paginate:

gem install will_paginate

添加到Gemfile并运行bundle。

<强>控制器

class DashboardController < ApplicationController
    include StructHelper

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

end

模块StructHelper查询服务,而不是数据库。 structHelperGet()返回一组记录。

不确定更复杂的解决方案是伪造模型,还是每隔一段时间获取数据并偶尔重新创建一个sqllite表并拥有一个真实的模型来查询。只是创建我的第一个rails应用程序。

查看

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

这将为您提供每页默认30行的分页。

如果您尚未阅读http://railstutorial.org,请立即开始阅读。

答案 6 :(得分:0)

即使没有任何宝石,也可以实现分页。我看到了这个How do I paginate an Array?。 kaminari gems文档中的简单实现。请参阅以下我从kaminari gems doc中获取的示例

var food = "pizza.png"
food_icon.setImageResource(R.drawable.food)//image is the pizza
food = "burger.png"
food_icon.setImageResource(R.drawable.food)//image is the burger