Human Attribute Override Plugin Tutorial
January 1st, 2008
This is my second tutorial covering the plugins that we’ve developed.
This tutorial covers the human attribute override plugin.
The plugin allows humanized versions of attributes to be overridden with custom strings to provide a better conversion than human_name may provide.
Why?
The main reason for creating this plugin is that Rails doesn’t always provide an acceptable “humanized” version of an attribute name.
Column.new('num_employees', ...).human_name # => 'Num employees'
You could argue that perhaps the attribute should be named number_of_employees..
Column.new('number_of_employees', ...).human_name # => 'Number of employees'
But this is hardly an acceptable solution for various reasons
- The attribute name is too wordy.
- Changing an attribute name for the sake of it’s humanized version reading better results in unneeded refactoring.
- You’re using a legacy database that uses a specific naming convention.
Rails Usage
Rails uses these humanized conversions in error reporting with the error_messages_for method via full_messages and in schema definitions for column names with the human_name method.
Using the above example, a table companies has a field called “num_employees”.
class Company < ActiveRecord::Base
end
Company.columns_hash['num_employees'].human_name # => 'Num employees'
Plugin Usage
So since the column name conversion in the previous example is basically unacceptable, let’s use the plugin to fix this up.
class Company < ActiveRecord::Base
attr_human_name 'num_employees' => 'Number of employees'
end
Company.columns_hash['num_employees'].human_name # => 'Number of employees'
The plugin provides an additonal method called attr_human_name that accepts a hash of “attribute name” => “desired humanized conversion text” pairs. The hash keys (the attribute names) can be specified as a string or a symbol.
Specifying more than one conversion…
class Company < ActiveRecord::Base
attr_human_name :num_employees => 'Number of employees', :unit_num => 'Unit #'
end
Company.columns_hash['num_employees'].human_name # => 'Number of employees'
Company.columns_hash['unit_num'].human_name # => 'Unit #'
If you’d like to retrieve a list of all of the overridden attributes, you can use human_name_attributes
Company.human_name_attributes # => {"num_employees"=>"Number of employees", "unit_num"=>"Unit #"}
Summary
So if you have some attributes that need better names for use in your rails views, use the plugin and make your life much easier.

on January 23rd, 2008 at 04:02 AM
I see it’s not working with Scaffolding generator – column names are humanized in standard way. Any clues?
Scaffolding generator code is a bit complicated and contains some tricks to create instances of a model to work with. This may be the reason?
on January 23rd, 2008 at 01:37 PM
The scaffold generator in Rails 2.x doesn’t appear to use the old column style found in Rails 1.x. As a side note, I haven’t used the Scaffold generator in ages.
What version of Rails are you using? Can you paste some code that displays the problem you’re experiencing? I’ll gladly look into it with more information.
Thanks
on February 13th, 2008 at 08:42 AM
Hi,
I opened a ticket with Rails Trac
- Re: [Rails Trac] #11094: attr_human_name criples rake db:create
It was closed with reason: bug in plugin.
Error: If you have attr_human_name in your models, they will criple your rake db:create (perhaps more – I have not tested)
Workaround: the work around is to comment out your attr_human_name lines in your models, rake the task, and uncomment.
I’m sorry to be the “messenger of ill tidings” – your plugin is a nice plugin.
So, thought you’d like to know anyway :)
Best regards, Walther
on February 13th, 2008 at 12:27 PM
Hmm, I’ll look into it. I haven’t run into the issue you describe, but I don’t use that rake command very often.
Thanks for reporting the problem.
on February 13th, 2008 at 12:38 PM
I can’t reproduce the problem. Can you post the error you received?
on March 20th, 2008 at 03:11 PM
Hi,
You have to first drop the database and then run the migrations to reproduce the error.
rake aborted! Mysql::Error: #42S02Table ‘topgim_dev.utilizadores’ doesn’t exist: SHOW FIELDS FROM `utilizadores` C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:150:in `log’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:132:in `execute’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/mysql_adapter.rb:281:in `columns’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1080:in `columns’ C:/Documents and Settings/tjpgfranco/My Documents/Personal/Projectos/Rails/topgim/vendor/plugins/human_attribute_override/lib/human_attribute_override.rb:14:in `attr_human_name’ C:/Documents and Settings/tjpgfranco/My Documents/Personal/Projectos/Rails/topgim/app/models/utilizador.rb:18 C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:203 C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:203:in `load’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:203:in `load_file’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:202:in `new_constants_in’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:318:in `load_file’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:202:in `require_or_load’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:248:in `load_missing_constant’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in `const_missing’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:465:in `const_missing’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/inflector.rb:257:in `module_eval’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/inflector.rb:257:in `constantize’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/core_ext/string/inflections.rb:148:in `constantize’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:143:in `observed_class’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:169:in `observed_classes’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:152:in `initialize’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/1.8/singleton.rb:95:in `new’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/1.8/singleton.rb:95:in `instance’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/1.8/singleton.rb:84:in `instantiate_observers’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:36:in `each’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:36:in `instantiate_observers’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:36:in `load_observers’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/initializer.rb:108:in `process’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/initializer.rb:49:in `run’ C:/Documents and Settings/tjpgfranco/My Documents/Personal/Projectos/Rails/topgim/config/environment.rb:13 C:/Documents and Settings/tjpgfranco/My Documents/Personal/Projectos/Rails/topgim/config/environment.rb:13:in `require’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/tasks/misc.rake:3 C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/tasks/misc.rake:2:in `call’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:546:in `execute’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:541:in `each’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:541:in `execute’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:541:in `invoke_with_call_chain’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:501:in `synchronize’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:501:in `invoke_with_call_chain’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:501:in `invoke_prerequisites’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:515:in `each’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1183:in `each’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:515:in `invoke_prerequisites’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:515:in `invoke_with_call_chain’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:501:in `synchronize’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:501:in `invoke_with_call_chain’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:501:in `invoke’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1931:in `invoke_task’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1909:in `top_level’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1909:in `each’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1909:in `top_level’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1909:in `standard_exception_handling’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1903:in `top_level’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1909:in `run’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1878:in `standard_exception_handling’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1878:in `run’ C:/Program Files/Aptana/Aptana Studio/plugins/org.jruby_1.1.0.5965_RC2p1/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:1878 C:/ruby/bin/rake:19:in `load’ C:/ruby/bin/rake:19 -e:2:in `load’ -e:2
on April 11th, 2008 at 04:19 PM
This is a handy plugin, but the lable form helper wasn’t displaying the humanized name. I ended up overriding the label helper. Here’s my solution. Works on Rails 2.0.2
http://pastie.caboo.se/179328
on April 23rd, 2008 at 03:43 AM
I think that you’ve forgot to include all necessary files to make rake test:plugins work. I’ve got an error with that plugin when running tests:
$ /usr/bin/ruby1.8 -Ilib:test ”/var/lib/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb” “vendor/plugins/human_attribute_override/test/attribute_human_name_test.rb” “vendor/plugins/human_attribute_override/test/human_attribute_override_test.rb” ./vendor/plugins/human_attribute_override/test/attribute_human_name_test.rb:1:in `require’: no such file to load—abstract_unit (LoadError) from ./vendor/plugins/human_attribute_override/test/attribute_human_name_test.rb:1 from /var/lib/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5:in `load’ from /var/lib/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5 from /var/lib/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5:in `each’ from /var/lib/gems/1.8/gems/rake-0.8.1/lib/rake/rake_test_loader.rb:5
on April 23rd, 2008 at 11:15 PM
I don’t think I have any tests for the plugin actually, but I’ll take a look and update it so it works with rake. Thanks for the heads up. I’ll try to get to this soon.
on July 14th, 2008 at 06:15 AM
Hi, Im facing the same error as reported by Tiago Franco.rake db:migrate is failing with the pluggin. If i comment out the attr_human_name from my model, everything works out fine.How to solve this problem ???
I have pasted the error below:
(in F:/saurav/Alterum/1st_rls+review)Thanks Saurav
on July 14th, 2008 at 08:13 AM
For those having issues with errors occuring during migrations, I’m not sure what the issue is. I’ve been using the plugin for ages now while using migrations and have never seen an error.
My initial guesses to the cause are something specific to the MySql adapter (I use Postgres for everything mainly) or you have another plugin installed causing some sort of a conflict.
There could be a problem with this plugin itself, but I can’t reproduce it, so my suggestion is to try and track down the issue in your own environment and send me a fix if you find one.
Thanks
on July 28th, 2008 at 01:14 PM
Hi Andrew, to reproduce this issue, try creating a new database for your application and running db:migrate. You should get an exception in the models where you’ve used the attr_human_name method. The problem is with
self.columns.reject{|c| !attributes.has_key?(c.name)}.each{|c| c.parent_record_class = self}
self.columns will execute a SHOW FIELDS FROM ‘table’ call to get the columns associated with that particular model. If that table doesn’t exist yet in the database, this will throw a mysql error. A relatively painless way of handling this is to add a check to make sure the table exists at the top of the method:
http://pastie.org/242634
on July 28th, 2008 at 01:30 PM
Thanks David. I’ve updated the plugin to include your fix.