简体   繁体   English

Ruby on Rails将对数组进行分页

[英]Ruby on Rails will_paginate an array

I was wondering if someone could explain how to use will_paginate on an array of objects? 我想知道是否有人可以解释如何在对象数组上使用will_paginate

For example, on my site I have an opinion section where users can rate the opinions. 例如,在我的网站上,我有一个意见栏,用户可以在其中对意见进行评分。 Here's a method I wrote to gather the users who have rated the opinion: 这是我编写的一种方法,用于收集对意见进行评分的用户:

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

Thank you 谢谢

will_paginate 3.0 is designed to take advantage of the new ActiveRecord::Relation in Rails 3, so it defines paginate only on relations by default. will_paginate 3.0旨在利用Rails 3中新的ActiveRecord::Relation ,因此默认情况下它仅在关系上定义paginate It can still work with an array, but you have to tell rails to require that part. 它仍然可以与数组一起使用,但是您必须告诉rails需要该部分。

In a file in your config/initializers (I used will_paginate_array_fix.rb ), add this 在您的config/initializers文件中(我使用will_paginate_array_fix.rb ),添加此文件

require 'will_paginate/array'

Then you can use on arrays 然后可以在数组上使用

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

You could use Array#from to simulate pagination, but the real problem here is that you shouldn't be using Array at all. 您可以使用Array#from来模拟分页,但是这里的真正问题是您根本不应该使用Array

This is what ActiveRecord Associations are made for. 这就是ActiveRecord关联的用途。 You should read that guide carefully, there is a lot of useful stuff you will need to know if you're developing Rails applications. 您应该仔细阅读该指南,如果您正在开发Rails应用程序,则需要了解很多有用的东西。

Let me show you a better way of doing the same thing: 让我向您展示做同一件事的更好方法:

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

It's important that your database schema is following the proper naming conventions or all this will break. 重要的是您的数据库架构要遵循正确的命名约定,否则所有这些都将破坏。 Make sure you're creating your tables with Database Migrations instead of doing it by hand. 确保使用数据库迁移来创建表,而不要手工完成。

These associations will create helpers on your models to make searching much easier. 这些关联将在您的模型上创建帮助器,以使搜索更加容易。 Instead of iterating a list of OpinionRatings and collecting the users manually, you can make Rails do this for you with the use of named_scope or scope depending on whether you're using Rails 2.3 or 3.0. 无需迭代OpinionRatings列表并手动收集用户,您可以使Rails使用named_scopescope实现此目的,这取决于您使用的是Rails 2.3还是3.0。 Since you didn't specify, I'll give both examples. 由于您未指定,因此我将给出两个示例。 Add this to your OpinionRating class: 将此添加到您的OpinionRating类:

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

scope :agreed, where(:agree => true)

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

In either case you can call for(id) on the OpinionRatings model and pass it an id: 无论哪种情况,您都可以在OpinionRatings模型上调用for(id)并将其传递给ID:

2.3 2.3

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

3.0 3.0

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

The upshot of all this is that you can now easily paginate: 所有这一切的结果就是您现在可以轻松地分页:

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

Update for Rails 4.x: more or less the same: Rails 4.x的更新:大致相同:

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

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

Although for newer Rails my preference is kaminari for pagination: 尽管对于较新的Rails,我更喜欢分页的kaminari

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

The gem will_paginate will paginate both ActiveRecord queries and arrays. gem will_paginate将对ActiveRecord查询和数组进行分页。

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

If you don't want to use the config file or are having trouble with it, you can also just ensure you return an ActiveRecord::Relation instead of an array. 如果您不想使用配置文件或遇到配置文件问题,也可以确保返回ActiveRecord :: Relation而不是数组。 For instance, change the agree_list to be a list of user ids instead, then do an IN on those ids to return a Relation. 例如,将同意列表列表改为用户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

This is inefficient from a database perspective, but it's an option for anybody having issues with the will_paginate config file. 从数据库的角度来看,这是低效的,但是对于will_paginate配置文件有问题的任何人来说,这都是一个选择。

I took advantage of rails associations, and came up with a new method: 我利用了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

In my view I looked up the profile like so: 在我看来,我像这样查找个人资料:

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

Please post up if there's a better way to do this. 如果有更好的方法,请发表。 I tried to use the named_scope helper in the OpinionRating model with no luck. 我试图在OpinionRating模型中使用named_scope帮助器,但没有运气。 Here's an example of what I tried, but doesn't work: 这是我尝试过但无法正常工作的示例:

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

That seemed like the same as using the find method though. 但这似乎与使用find方法相同。

Thanks for all the help. 感谢您的所有帮助。

I am using rails 3 ruby 1.9.2. 我正在使用Rails 3 ruby​​ 1.9.2。 Also, I am just starting app, so no css or styles included. 另外,我只是启动应用程序,因此不包括CSS或样式。

Install will_paginate: 安装will_paginate:

gem install will_paginate 宝石安装will_paginate

Add to Gemfile and run bundle. 添加到Gemfile并运行包。

Controller 控制者

class DashboardController < ApplicationController
    include StructHelper

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

end

module StructHelper queries a service, not a database. StructHelper模块查询服务,而不是数据库。 structHelperGet() returns an array of records. structHelperGet()返回记录数组。

Not sure if a more sophisticated solution would be to fake a model, or to grab the data every so often and recreate a sqllite table once in a while and have a real model to query. 不知道更复杂的解决方案是伪造模型,还是经常抓取数据并不时地重新创建sqllite表,并拥有要查询的真实模型。 Just creating my first rails app ever. 刚刚创建了我的第一个Rails应用程序。

View 视图

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

This will give you pagnation of the default 30 rows per page. 这将使您分页默认为每页30行。

If you have not read http://railstutorial.org yet, start reading it now. 如果您尚未阅读http://railstutorial.org ,请立即开始阅读。

You can implement pagination even without any gem.I saw this How do I paginate an Array? 即使没有任何宝石,您也可以实现分页。 看到了如何分页数组? . Simple implementation in kaminari gems doc. kaminari gems文档中的简单实现。 Please see the below example which i got from kaminari gems doc 请参阅以下我从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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM