2011-02-09 68 views
6

我的应用程序有几个报告,我试图为所有这些集合制作group_by的辅助方法。Rails - group_by

例子:

def group_collection(collection, options = {}) 
    column = options[:column] 
    group_count = collection.group_by{ |item| item.column.strftime('%b %y')} 
end 

这是我打算如何使用它

@user_groups = group_collection(@users, :column => "created_at") 

不幸的是,这是行不通的。

undefined method `column' for... [CollectionObject] 

如何,因此认为自己的ActiveRecord列,而不是一个实例方法,使“列”变量的实际列类型在运行时任何线索?

回答

21

忽略一些在你的代码中的其他问题,你想用column做什么可以做,像这样:

collection.group_by { |item| item.send(column).strftime('%b %y') } 

这工作,因为在Ruby中访问实例变量的方法是通过访问方法(通常以您尝试访问的变量的名称命名),因此@item.foobar@item上调用foobar方法。

现在,回到那些“其他问题”。你试图将重复的行为转移到一个地方是非常好的,并且它表明你在考虑灵活性时不太明确地考虑可扩展性。但是,在这里,有几件事情对你来说不会很好解决,我不得不指出。

  1. 分组对大量数据类型起作用,其中大多数不响应strftime。通过硬编码对它的调用,您引入了意外行为,这意味着您无法运行group_collection(@users, :column => 'phone_number')。相反,只有在测试列数据可以对其做出响应之后才运行它。

    collection.group_by do |item| 
        data = item.send(column) 
        data.respond_to?(:strftime) ? data.strftime('%b %y') : data 
    end 
    
  2. 如果明确这个辅助方法的行为是组上的任意列,可以接受沟的选项哈希额外的复杂性,只能绕过它。

    def group_by_column(collection, column) 
        collection.group_by { ... } 
    end 
    group_by_column(@users, :column) 
    
  3. 您可以按任意列组要容易得多,你使用Ruby 1.9+,你不需要做任何额外的格式提供..

    @users.group_by &:created_at 
    
+0

谢谢。这工作。你在代码中看到了哪些其他问题?我将不得不再等待7分钟以将此标记为已回答。 :) – AMIT 2011-02-09 19:02:21

2
def group_collection(collection, options = {}) 
    column = options[:column] 
    group_count = collection.group_by{ |item| item.send(column).strftime('%b %y')} 
end