Skip to content

Instantly share code, notes, and snippets.

@brookr
Created May 15, 2012 06:24
Show Gist options
  • Select an option

  • Save brookr/2699567 to your computer and use it in GitHub Desktop.

Select an option

Save brookr/2699567 to your computer and use it in GitHub Desktop.
Add collector methods for all attributes on objects in an array.
class Array
def method_missing(method_name, *args, &block)
if method_name.to_s.is_plural?
map{ |e| e.send(method_name.to_s.singularize) }
else
super
end
end
def respond_to?(method_name, include_private = false)
method_name.to_s.is_plural? ? true : super
end
end
class String
def is_plural?
pluralize == self
end
end
@brookr

brookr commented May 15, 2012

Copy link
Copy Markdown
Author

Yay! Now I can write User.all.ids instead of the unsightly and awkwardly-typed User.all.map(&:id). So much easier on the pinkies! Also much easier to read.

Any good arguments against doing this?

(Tomorrow, I'll add the class method, so it can be just User.ids. Scandalous!)

@krainboltgreene

Copy link
Copy Markdown
  1. Have the to_s happen in is_plural? and you'll save yourself a method call.
  2. This is probably the Databases job, not Ruby. Especially if it's SQL.
  3. Do you not have to pass those parameters to super?
  4. Your map could look like this: map(&method_name.singularize.to_sym)` ... I think.

@krainboltgreene

Copy link
Copy Markdown

Oh, and make this into a microgem instead.

@krainboltgreene

Copy link
Copy Markdown

(Tomorrow, I'll add the class method, so it can be just User.ids. Scandalous!)

You've just described a scope. Well, a poorly named one. You'd have something like this:

class User < ActiveRecord::Base
  scope :ids, order(:id).select(:id)
end

It's probably a brazillion times faster, and also trackable better (because it's in SQL).

@brookr

brookr commented May 15, 2012

Copy link
Copy Markdown
Author

Thanks, Kurtis! Great ideas.

  1. method_name comes in as a symbol, but I can put is_plural? on the Symbol class to simplify the method_missing check a bit. Seemed more useful on String, but no reason to not have it on both!
  2. There are definitely cases where a scope is the better solution. But this also makes some scope-calling/-building easier.
  3. I'm not sure, having not mucked with method_missing much, but the examples I found do not seem to need to pass the params on.
  4. I'd have to .to_s it first to singularize it. Maybe Symbol#singularize would be a good candidate to include here as well for tidyness.

Rockin. You are right, this is solid microgem territory.

Appreciate the comments!

@brookr

brookr commented May 15, 2012

Copy link
Copy Markdown
Author

Yeah, the class version is scope-like, for sure. I'll think about adding scopes based on attribute names. I don't think I come across as many use cases for that, but it sure could be handy in the console when troubleshooting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment