【问题标题】:will_paginate with named_scopeswill_paginate 与 named_scopes
【发布时间】:2011-02-17 00:56:55
【问题描述】:

我正在使用 will_paginate 进行分页,到目前为止效果很好,除了这一件事。

例如,如果我尝试对范围进行分页

class User < ActiveRecord::Base

    named_scope :scope, lambda { etc }

end

User.scope.paginate({:page => params[:page], :per_page => 10})

这会告诉我 paginate 是一个未定义的方法。我宁愿不必只为这个范围使用第二种解决方案,有什么我可以在这里做的吗?

【问题讨论】:

    标签: ruby-on-rails named-scope will-paginate


    【解决方案1】:

    Lowgain,klew 的版本应该开箱即用。在你的版本中你应该写:

    User.scope.paginate :page => params[:page], :per_page => 10
    

    我更喜欢另一种分页方法。它允许使控制器更干净并在模型级别封装分页,例如:

    class Property < ActiveRecord::Base
      named_scope :all_properties, lambda {{ :order => "name asc" }}
    
      def self.admin_properties(page = 1)
        self.all_properties.paginate(:page => page, :per_page => Settings.admin.per_page)
      end
    end
    

    并且在控制器中非常清晰的代码:

    class Admin::PropertiesController < Admin::AdminController
      def index
        @properties = Property.admin_properties(params[:page])
      end
    end
    

    ps:Settings.admin.per_page - 这是Searchlogic 设置。

    【讨论】:

    • 嗯,这很有趣!这样做是否有任何明显的性能缺陷,因为它会对每个属性进行分页?
    • 如何对每个属性进行分页? :) 不是所有的,而是所有的。命名范围 all_properties 是一种类方法(不是实例!)。因此,当我们调用 self.all_properties 时,我们会从这个命名范围中接收所有属性。然后我们对它们进行分页。 Self 表示类属性本身 - 不是类属性的对象。
    【解决方案2】:

    我有一个这样定义的named_scope

     named_scope :look_for, lambda { |search| bla;bla;bla }
    

    我称之为:

     Person.look_for(params[:search]).paginate :page => params[:page]
    

    而且它有效。也许您的范围需要一些参数?

    【讨论】:

    • hmm,你期望什么样的参数?范围似乎在分页之外工作
    • 如果你的范围有参数,那么你应该给一个。如果没有,那么不要;)。我的例子是带参数的。
    【解决方案3】:

    有点奇怪的解决方案,但是

    User.scope.find(:all).paginate :page => params[:page], :per_page => 10
    

    有效吗?

    【讨论】:

      【解决方案4】:

      Lowgain,听起来不像你,但只是为了确保 -- 你实际上并没有使用名为 scope 的 named_scope 进行测试,对吗?因为 scope 是一个现有的方法,并且使用它作为你的范围名称会导致错误(和无限循环)。

      编辑:

      您的 named_scope 是否恰好包含 :limit 子句?我刚开始遇到类似的问题。我有一个属于用户的模型响应,其命名范围如下:

      named_scope :top, lambda { |limit| {
                  :limit => limit,
                  :order => 'total_score DESC' }}
      

      我在控制台中看到如下结果:

      ?> u = User.find 1
      ?> u.responses.length
      => 9
      ?> u.responses.paginate(:page => 1, :per_page => 5).length
      => 5
      ?> u.responses.top(3).length
      => 3
      ?> u.responses.top(3).paginate(:page => 1, :per_page => 5).length
      => 5
      

      哎呀!我的前 3 个分页如何生成超过 3 行?根据您的示例,我尝试了您的 find(:all) 技巧,结果相似:

      ?> u.responses.top(3).find(:all).paginate(:page => 1, :per_page => 5).length
      => 3
      

      这看起来像是 named_scope 中的一个错误,因为我可以将 will_paginate 排除在外,并引发类似的混乱:

      ?> u.responses.top(3).length
      => 3
      ?> u.responses.top(3).size
      => 9                       <-- .size produces wrong answer
      ?> r = u.responses.top(3)
      ?> r.size
      => 3                       <-- correct when result assigned to var
      

      到目前为止,这似乎只在我使用 MySQL 时发生。我想我在 StackOverflow 上阅读了另一篇文章,其中有人在使用 .size 与 AR 结果和 MySQL 时遇到了类似的问题,解决方案是始终在他们的 AR 结果上使用 .length。我曾尝试修改 will_paginate 以将 .size 的所有实例替换为 .length,但这并不是那么简单,但我怀疑这个或类似的问题会以某种方式影响 will_paginate。

      目前,我正在使用你的 find(:all) 技巧来解决这个问题。

      【讨论】:

      • 刚刚意识到我 2 个月前在博客上写过同样的事情,忘记了它,然后今天“重新发现”了它。我讨厌变老!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-15
      相关资源
      最近更新 更多