2011-02-09 69 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