Rails 4:尝试根据计算值对资源进行排序时会出现错误

时间:2015-01-14 14:05:07

标签: ruby-on-rails ruby sorting ruby-on-rails-4 will-paginate

我使用Rails 4.1.0我想根据完整性对配置文件进行排序所以为此我在我的个人资料模型中有这个代码

def completeness
    percent = 10

    percent += 15 if self.useravatar.present?
    percent += 5 if self.summary.present?
    percent += 5 if self.profile_languages.present?
    percent += 10 if self.educations.present?
    return percent
end

def self.sorted_by_completeness
  Profile.all.sort_by(&:completeness).reverse
end

这是我的个人资料索引控制器

  def index
    @profiles = Profile.paginate(page: params[:page], per_page: 10).sorted_by_completeness
  end 

但是,当我尝试访问个人资料索引页面时,我收到此错误undefined method total_pages'对于#有人可以告诉我为什么我会收到此错误

3 个答案:

答案 0 :(得分:1)

sort_by将返回Array集合

测试打开rails控制台并输入

Profile.all.sort_by(&:completeness).reverse.class

让will_paginate使用数组,您需要require 'will_paginate/array' 所以只需将profile_controller更改为

require 'will_paginate/array'
class ProfileController < ApplicationController
  def index
    @profiles = Profile.sorted_by_completeness.paginate(page: params[:page], per_page: 10)
  end 
end

答案 1 :(得分:1)

您的方法存在两个问题:

  1. 在您看来,您可能正在使用will_paginate(@projects)失败,因为该方法不适用于数组。

  2. 您在分页后对行进行排序。这意味着无论您对它们进行排序,排序一次只能应用于一个页面。因此,无论您选择何种解决方案,都需要在对数据进行分页之前指定顺序。

  3. 解决方案是显然在您的阵列上使用分页。类似的东西:

    require 'will_paginate/array' # to enable pagination on an array
    @projects = Project.sorting_method.paginate(arguments)
    

    然而,对于大量项目而言,这很快就会变得不切实际。

    启用分页的最佳方式是,completeness表中的projects字段会随时更新。然后,您可以非常轻松地执行以下操作:

    @projects = Project.order("completeness DESC").paginate(arguments)
    

    另一种解决方案是在SQL select语句中使用子查询来计算每个项目的完整性。类似的东西:

    lcq = "SELECT COUNT(*) FROM profile_languages WHERE
      (profile_languages.project_id = projects.id)"
    ecq = "SELECT COUNT(*) FROM educations WHERE
      (educations.project_id = projects.id)"
    
    @projects = \
      Project.select(
        "#{project.column_names.join(',')},
        SELECT(
          (CASE useravatar WHEN NULL THEN 0 ELSE 15 END) +
          (CASE summary WHEN NULL THEN 0 ELSE 5 END) +
          (CASE (#{lcq}) WHEN 0 THEN 0 ELSE 5 END) +
          (CASE (#{ecq}) WHEN 0 THEN 0 ELSE 10 END)
        ) AS completeness").
      order("completeness DESC").
      paginate(arguments)
    

    通过一些调试,这应该工作。我不喜欢它。一堆难以阅读的代码和可能会减慢很多事情的子查询。

答案 2 :(得分:0)

 def index
  @profiles = Profile.sorted_by_completeness(params[:page])
 end

在您的模型文件中:

def self.sorted_by_completeness(current_page)
    Profile.all.sort_by(&:completeness).reverse.paginate(page: current_page)
end

要在代码下方定义per_page限制,请使用

 #app/config/initializers/will_paginate.rb 
  WillPaginate.per_page = 10

否则,如果您想在模型级别中定义它:

  #profile.rb
   class Profile < ActiveRecord::Base
      self.per_page = 10
    #your other model level logic goes here.
    end