75

我想知道是否有人可以解释如何在对象数组上使用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

谢谢

4

7 回答 7

223

will_paginate 3.0 旨在利用ActiveRecord::RelationRails 3 中的新功能,因此paginate默认情况下它仅定义关系。它仍然可以与数组一起使用,但是您必须告诉 rails 需要该部分。

在你的config/initializers(我用过的will_paginate_array_fix.rb)文件中,添加这个

require 'will_paginate/array'

然后你可以在数组上使用

my_array.paginate(:page => x, :per_page => y)
于 2011-12-06T21:45:31.960 回答
9

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

这就是ActiveRecord 关联的用途。您应该仔细阅读该指南,如果您正在开发 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

重要的是您的数据库架构遵循正确的命名约定,否则这一切都会中断。确保您使用数据库迁移创建表,而不是手动创建表。

这些关联将在您的模型上创建助手,使搜索更容易。named_scope您可以让 Rails 使用或scope根据您使用的是 Rails 2.3 还是 3.0,而不是迭代 OpinionRatings 列表并手动收集用户。由于您没有指定,我将给出两个示例。将此添加到您的 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])
于 2010-12-04T10:07:46.887 回答
4

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

list = OpinionRating.where(:opinion_id => params[:id]).includes(:profile).paginate(:page => params[:page])
@agree_list = list.map(&:profile)
于 2010-12-04T10:10:13.597 回答
1

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

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

从数据库的角度来看,这是低效的,但对于任何对 will_paginate 配置文件有问题的人来说,这是一个选择。

于 2013-06-28T22:13:33.917 回答
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 方法相同。

感谢所有的帮助。

于 2010-12-04T12:24:35.920 回答
0

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

安装 will_paginate:

宝石安装 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,请立即开始阅读。

于 2011-03-18T01:24:56.263 回答
0

即使没有任何 gem,您也可以实现分页。我看到了如何对数组进行分页?. kaminari gems 文档中的简单实现。请参阅我从 kaminari gems doc 获得的以下示例

arr = (1..100).to_a
page, per_page = 1, 10
arr[((page - 1) * per_page)...(page * per_page)] #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
page, per_page = 2, 10
arr[((page - 1) * per_page)...(page * per_page)] #=> [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
于 2019-05-22T14:24:25.767 回答