Apologies if this was already posted, I sent this over the weekend via
Google groups and it never showed up. So I''m trying again. :-)
A while back I had an idea for extending Array#collect to work like the
ActiveRecord find_by_* method_missing method. I put it on the back
burner until I was showing a co-worker a bit about Ruby on Rails and
realized how convenient such a feature could be. As we all know Ruby is
such a fantastic language that it makes these sorts of things easy, and
sure enough it was a simple little hack. I thought I''d post it here in
case others might find it useful.
Here''s how collect normally works:
locations = Location.find(:all)
just_the_names_and_ids = locations.collect{|loc| [loc.id, loc.name]}
=> [[1, "New York Zone"], [2, "Los Angeles Zone"], [4,
"Boston Zone"],
[5, "San Francisco Zone"], [6, "Development Center"]]
Here it is with the new collect_* feature:
just_the_names_and_ids = locations.collect_id_and_name
=> [[1, "New York Zone"], [2, "Los Angeles Zone"], [4,
"Boston Zone"],
[5, "San Francisco Zone"], [6, "Development Center"]]
just_the_names = locations.collect_name
=> [["New York Zone"], ["Los Angeles Zone"],
["Boston Zone"], ["San
Francisco Zone"], ["Development Center"]]
names_and_cities = locations.collect_name_and_city
=> [["New York Zone", "New York"], ["Los Angeles
Zone", "Los Angeles"],
["Boston Zone", "Boston"], ["San Francisco Zone",
"San Francisco"],
["Development Center", "Chicago"]]
Just like the find_by_* methods you can use any attribute name _and_
any additional attribute names instead of {|array| [array.x, array.y,
array.z]} etc. Of course the original way still works too.
It''s not limited to one _and_, so you can do as many as you want:
names_cities_and_ids = locations.collect_id_and_name_and_city
Or even:
even_more
locations.collect_id_and_name_and_city_and_state_and_zip_code_and_relative_humidity_and_enough_already
You get the idea. :-)
Caveats are that it won''t work with included associations,
you''ll need
to resort to a block for that. There''s nothing technically difficult
about adding that feature but I couldn''t think of a clean syntax for
allowing it. Any suggestions are welcome.
To add this functionality just paste the code below into environment.rb
(or include it from a .rb file in /lib). This could also be made into a
plugin. I''ll make one if anyone is interested.
class Array
def method_missing(method_id, *arguments)
if match = /collect_([_a-zA-Z]\w*)/.match(method_id.to_s)
attributes = match.captures.last.split(''_and_'')
self.collect{|array| attributes.collect{|attr|
array[attr.to_sym]}}
else
super
end
end
end
Full back story with other examples are at
http://dashing.com/blog/2006/12/09/super_easy_collect_for_activerecord_arrays
It also works with Arrays of hashes too.
I hope someone finds this useful.
Cheers,
John
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---