common_name

Stop needing to use humanize/downcase/underscore/pluralize/to_sym/etc to derive a common name.

Why this is useful

In our app, we have lots of classes that share something (a name) in common:

  • class Automobile < Emitter

  • class AutomobilesController < EmittersController

  • class AutomobilesComponent < Component

  • class AutomobileVersion < EmitterVersion

  • Boat et al., Flight et al., etc.

Of course, there are a million ways to derive the word “automobile” from any of these class names. We could fill up our app with humanize/downcase/underscore/pluralize, but we think that’s sloppy.

So we use common_name:

>> Automobile.common_name
=> "automobile"
>> Automobile.new.common_name
=> "automobile"
>> AutomobilesController.common_name
=> "automobile"
>> AutomobilesController.new.common_name
=> "automobile"
>> AutomobilesComponent.common_name
=> "automobile"
>> AutomobilesComponent.new.common_name
=> "automobile"
>> AutomobileVersion.common_name
=> "automobile"
>> AutomobileVersion.new.common_name
=> "automobile"

And when metaprogramming:

module EmitterVersionExtensions
  def self.included(klass)
    klass.class_eval do
      set_table_name "#{common_name}_versions"        # set_table_name "automobile_versions"
      belongs_to common_symbol                        # belongs_to :automobile
      has_one :profile, :through => common_symbol     # has_one :profile, :through => :automobile
    end
  end
end

We also end up using this constantly in views.

Quick reference

Here are all the methods it gives you:

common_name             => "bus_company"
common_symbol           => :bus_company
common_instance         => "@bus_company"
common_title            => "Bus company"
common_human            => "bus company"
common_camel            => "BusCompany"

common_plural           => "bus_companies"
common_plural_symbol    => :bus_companies
common_plural_instance  => "@bus_companies"
common_plural_title     => "Bus companies"
common_plural_human     => "bus companies"
common_plural_camel     => "BusCompanies"

common_model            => BusCompany [the class]

Quick start

Put this in config/environment.rb

config.gem 'common_name'

Put this in config/initializers/common_name.rb… (it will let you say BusCompany.common_name and get the string “bus_company”)

ActiveRecord::Base.class_eval do
  class << self; def _common_name; name.underscore; end; end
  include CommonName
end

Put this in app/controllers/application_controller.rb… (in the CareersController, it will let you say common_model and get the class Career)

class ApplicationController < ActionController::Base
  class << self; def _common_name; controller_name.singularize; end; end
  include CommonName
end

Put this in app/helpers/application_helper.rb… (in careers/show, it will let you say <%= common_plural_title %> and see “Careers”)

module ApplicationHelper
  CommonName::METHODS.each do |m|
    eval %{ def common_#{m}; controller.common_#{m}; end }
  end
end

What it’s not

It’s not a replacement for humanize, pluralize, etc.

>> "bus_company".common_title
NoMethodError: undefined method 'common_title' for "bus company":String

The point is to cover common names of classes and their instances.

Advanced usage

The _common_name method should provide an underscored form that will be used to derive other common forms like common_human and common_plural_symbol.

Note that calling common_X on a class and on its instances will return the same value.

I also use it on non-ActiveRecord classes:

class FooBar
  class << self; def _common_name; name.underscore; end; end
  include CommonName
end

>> FooBar.common_name
=> "foo_bar"
>> f.common_name         # f = FooBar.new
=> "foo_bar"

If you define _common_plural, it will be the basis for the plural forms:

class Government
  class << self
    def _common_name
      'government'
    end
    def _common_plural
      'government'
    end
  end
  include CommonName
end

That way you can enforce uncountability

Government.common_name == Government.common_plural

without setting a general rule in the Inflector that the word “government” is uncountable.

Rationale

I don’t like chains of humanize/downcase/underscore/pluralize/to_sym, for example:

>> BusCompany.name.underscore.humanize.downcase.pluralize
=> "bus companies"

So I replaced them with easy-to-remember methods like:

>> BusCompany.common_plural_human
=> "bus companies"

I also didn’t like worrying about .name versus .class.name:

>> @bus_company.class.name      # @bus_company = BusCompany.new
=> "BusCompany"
>> @bus_company.name
=> ""

So, the common_name of a class (BusCompany) is always equivalent to the common_name of its instances (@bus_company):

>> BusCompany.common_plural_human == @bus_company.common_plural_human
=> true

Copyright © 2009 Seamus Abshere. See LICENSE for details.