使用Rails 3,Ruby 1.9.2,如何在不是DB列的列上对表进行排序?

时间:2011-10-13 15:54:17

标签: jquery ruby-on-rails ruby-on-rails-3

很容易,在此railscast http://railscasts.com/episodes/240-search-sort-paginate-with-ajax之后,能够创建一个基于我的数据库中存在的列进行排序的表。但我在我的表中显示的其他列不是数据库列,我仍然需要按这些列排序。

例如,我有多个列来组成捐赠者名称(prefix1,first_name1,middle_name1,last_name1,suffix1,prefix2,first_name2,middle_name2,last_name2,suffix2,company)。我在我的模型中定义了“who_donated”,它是使用我给出的一些规则的实际表列的组合。所以基本上我显示的捐赠者表格中有一个who_donated字段,我希望能够对该字段进行排序。

如果该列不是数据库表中的实际列,我如何对视图表的列进行排序?

2 个答案:

答案 0 :(得分:1)

因为我有很多不同的方法来收集信息以放入我需要排序的列中,因为可能有很多行可以排序,我决定将尽可能多的工作放在mysql服务器上尽可能为每个案例进行排序。

这就是我解决它的方法......我几乎跟着railscast 228和240进行初始设置:http://asciicasts.com/episodes/228-sortable-table-columns和http://asciicasts.com/episodes/240-search-sort-paginate-with-ajax

然后我做了一些修改如下。

donors_controller:

def last_sort_column
  params[:sort].blank? ? 'created_at' :  params[:sort]
end 

def sort_column
  case 
    when Donor.column_names.include?(params[:sort]) then params[:sort]
    when params[:sort] == 'Donors' then 
        'concat(prefix1,first_name1,middle_name1,last_name1,suffix1,
        prefix2,first_name2,middle_name2,last_name2,suffix2,company)' 
    when params[:sort] == 'First Donated' then
         '(select min(donations.created_at) from donations where donations.donor_id = donors.id)'       
    when params[:sort] == 'Last Donated' then
         '(select max(donations.created_at) from donations where donations.donor_id = donors.id)'       
    when params[:sort] == 'Times Donated' then
         '(select count(*) from donations where donations.donor_id = donors.id)'       
    when params[:sort] == 'Total Amount' then
         '(select sum(amount) from donations where donations.donor_id = donors.id)'       
    else 'created_at'
  end
end

def sort_direction
  %w[asc desc].include?(params[:direction]) ?  params[:direction] : "asc"
end

和application_helper:

def sortable(column, title = nil)
  title ||= column.titleize
  css_class = (column == last_sort_column) ? "current #{sort_direction}" : nil
  direction = (column == last_sort_column && sort_direction == "asc") ? "desc" : "asc"
  link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end

添加last_sort_column是因为发送到order by语句的sort_column与列名不匹配,所以它永远不会记住你已经分类为asc或desc的内容。

这允许我把我想要的sql语句疯狂地放入排序中,但仍然完全阻止了sql注入的任何可能性,因为url只会显示列的实际名称。如果输入了我允许的有效选项以外的其他内容,则默认为created_at并抛弃虚假值。

我真的很惊讶这是如何快速排序超过100k行链接到另外200k行。

答案 1 :(得分:0)

最简单的情况:

<% sorted_donors = @unsorted_donors.sort_by{ |donor| donor.who_donated } %>

在此处阅读有关sort_by的更多信息:http://www.ruby-doc.org/core-1.9.2/Enumerable.html#method-i-sort_by

就像我说的,直接将这些代码放入视图中是获得所需排序的最丑陋,最简单的方法。如果你正在进行分页,你需要在分页之前在控制器中进行排序等等......但是这段代码至少应该让你朝着正确的方向前进。