2011-02-09 21 views
6

Ứng dụng của tôi có một vài báo cáo và tôi đang cố gắng tạo phương thức trợ giúp cho group_by cho tất cả các bộ sưu tập này.Rails - group_by

Ví dụ:

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

Đây là làm thế nào tôi có kế hoạch để sử dụng nó

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

Thật không may, điều này không làm việc.

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

Bất kỳ manh mối nào về cách làm cho cột "" biến một loại cột thực tế khi chạy để nó tự coi mình là cột đối tượng chứ không phải là một phương pháp thể hiện?

Trả lời

21

Bỏ qua một số vấn đề khác trong mã của bạn, những gì bạn đang cố gắng để làm với column thể được thực hiện như sau:

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

này hoạt động bởi vì trong Ruby theo cách bạn truy cập các biến dụ là thông qua các phương thức truy cập, thường được đặt tên theo biến bạn đang cố gắng truy cập, do đó, @item.foobar gọi phương thức foobar trên @item.

Bây giờ, hãy quay lại những "sự cố khác" đó. Thật tuyệt khi bạn đang cố gắng di chuyển hành vi lặp đi lặp lại vào một nơi duy nhất và nó cho thấy bạn đang suy nghĩ về khả năng mở rộng khi bạn làm cho mọi thứ ít rõ ràng hơn để có thể linh hoạt. Tuy nhiên, có một vài điều mà không phải là đi làm việc ra rất tốt cho bạn ở đây mà tôi cảm thấy bắt buộc phải chỉ ra.

  1. Tính năng nhóm hoạt động trên nhiều loại dữ liệu, hầu hết trong số đó không trả lời strftime. Bằng cách mã hóa cứng cuộc gọi đến đó, bạn đang giới thiệu hành vi không mong muốn có nghĩa là bạn không thể chạy group_collection(@users, :column => 'phone_number'). Thay vào đó, chỉ chạy sau khi kiểm tra dữ liệu cột có thể phản hồi nó.

    collection.group_by do |item| 
        data = item.send(column) 
        data.respond_to?(:strftime) ? data.strftime('%b %y') : data 
    end 
    
  2. Nếu bạn móng tay xuống hành vi của phương pháp helper này là nhóm trên một cột tùy ý, bạn có thể bỏ cái dự án phức tạp thêm việc chấp nhận một tùy chọn băm, chỉ để phá vỡ nó.

    def group_by_column(collection, column) 
        collection.group_by { ... } 
    end 
    group_by_column(@users, :column) 
    
  3. Bạn có thể nhóm bởi một cột tùy ý dễ dàng hơn nhiều, miễn là bạn đang sử dụng của Ruby 1.9+ và bạn không cần phải làm bất cứ định dạng bổ sung ..

    @users.group_by &:created_at 
    
+0

Cảm ơn . Điều đó hiệu quả. Bạn thấy những vấn đề nào khác trong mã? Tôi sẽ phải đợi thêm 7 phút để đánh dấu câu trả lời này. :) – AMIT

+0

Đã cập nhật với "các sự cố khác". :) – coreyward

+0

Tuyệt vời! Cảm ơn các chi tiết. Bạn đúng rồi. Việc nhóm cũng có thể ở trên các kiểu dữ liệu khác. Và tôi sẽ mương băm tùy chọn. Cảm ơn một lần nữa. – AMIT

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