2011-02-09 13 views
6

Moja aplikacja ma kilka raportów i próbuję stworzyć pomocniczą metodę dla group_by dla wszystkich tych kolekcji.Rails - group_by

Przykład:

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

To jak mam zamiar używać go

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

Niestety, to nie zadziała.

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

Wszelkie wskazówki dotyczące sposobu, aby „kolumnę” zmienna rzeczywista typ kolumny w czasie wykonywania tak uzna się jako kolumny ActiveRecord a nie metody instancji?

Odpowiedz

21

Ignorowanie niektórych innych problemów w kodzie, co chce zrobić z column można zrobić tak:

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

To działa, ponieważ w Ruby sposób uzyskać dostęp do zmiennych instancji jest przez metody dostępu, zwykle nazwane po zmiennej, do której próbujesz uzyskać dostęp, więc @item.foobar dzwoni do metody foobar na @item.

Teraz wracamy do tych "innych problemów". Wspaniale, że próbujesz przenieść powtarzające się zachowanie w jedno miejsce i pokazuje, że myślisz o rozszerzalności, gdy robisz mniej jasno na rzecz bycia elastycznym. Jest jednak kilka rzeczy, które nie sprawdzą się tutaj bardzo dobrze, dlatego czuję się zmuszony zwrócić na to uwagę.

  1. Grupowanie działa na wielu typów danych, z których większość nie reagują na strftime. Poprzez twarde kodowanie połączenia z nim wprowadzasz nieoczekiwane zachowanie, co oznacza, że ​​nie możesz uruchomić group_collection(@users, :column => 'phone_number'). Zamiast tego uruchom tylko to po przetestowaniu, czy dane kolumny mogą na nie odpowiedzieć.

    collection.group_by do |item| 
        data = item.send(column) 
        data.respond_to?(:strftime) ? data.strftime('%b %y') : data 
    end 
    
  2. Jeśli paznokci w dół zachowanie tej metody pomocnika jest do grupy o dowolnej kolumnie, można rów dodatkową złożoność akceptując hash opcji, tylko aby go obejść.

    def group_by_column(collection, column) 
        collection.group_by { ... } 
    end 
    group_by_column(@users, :column) 
    
  3. Można grupować według dowolnej kolumny znacznie łatwiej, pod warunkiem, że używasz Ruby 1.9+ i nie trzeba wykonywać żadnych dodatkowych formatowanie ..

    @users.group_by &:created_at 
    
+0

Dzięki . To się udało. Jakie inne problemy widzisz w kodzie? Będę musiał poczekać kolejne 7 minut, aby oznaczyć to jako odpowiedź. :) – AMIT

+0

Zaktualizowano "innymi problemami". :) – coreyward

+0

Awesome! Dzięki za szczegóły. Masz rację. Grupowanie może również dotyczyć innych typów danych. I zamierzam zrezygnować z opcji mieszania również. Dzięki jeszcze raz. – AMIT

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