Rails - group_by
My application has a few reports and I'm trying to make a helper method for group_by for all these collections.
Example:
def group_collection(collection, options = {})
column = options[:column]
group_count = collection.group_by{ |item| item.column.strftime('%b %y')}
end
This is how i plan to use it
@user_groups = group_collection(@users, :column => "created_at")
Unfortunate开发者_JAVA百科ly, this does not work.
undefined method `column' for... [CollectionObject]
Any clues on how to make the "column" variable an actual column type at runtime so it considers itself as activerecord column and not a instance method?
Ignoring some of the other problems in your code, what you are trying to do with column
can be done like so:
collection.group_by { |item| item.send(column).strftime('%b %y') }
This works because in Ruby the way you access instance variables is through accessor methods, usually named after the variable you're trying to access, so @item.foobar
calls the foobar
method on @item
.
Now, back to those "other problems". It's great that you're trying to move repeated behavior into a single place, and it shows you're thinking about extensibility when you make things less explicit in favor of being flexible. However, there are a couple of things that aren't going to work out very well for you here that I feel compelled to point out.
Grouping works on lots of data types, most of which don't respond to
strftime
. By hard coding the call to it you're introducing unexpected behavior that means you can't rungroup_collection(@users, :column => 'phone_number')
. Instead, only run that after testing that the column data can respond to it.collection.group_by do |item| data = item.send(column) data.respond_to?(:strftime) ? data.strftime('%b %y') : data end
If you nail down the behavior of this helper method is to group on an arbitrary column, you can ditch the additional complexity of accepting an options hash, only to circumvent it.
def group_by_column(collection, column) collection.group_by { ... } end group_by_column(@users, :column)
You can group by an arbitrary column much more easily, provided you're using Ruby 1.9+ and you don't need to do any additional formatting..
@users.group_by &:created_at
def group_collection(collection, options = {})
column = options[:column]
group_count = collection.group_by{ |item| item.send(column).strftime('%b %y')}
end
精彩评论