Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add readable field descriptions to ActiveRecord models

I'd like to add descriptions to ActiveRecord model fields to serve as basic instructions / examples for each of the fields. Basically model metadata. I can then display these in the UI (next to the fields on a form etc.)

The way I'm planning to do it is simply create a static hashtable inside the model with the field name as the key and description as the value. I.e.

FIELD_DESCRIPTIONS = {
  'category' => 'Select the category it should appear within.',
  'title' => 'The title should be a short but descriptive summary.',
  'description' => 'Please enter a full description.'
}

etc.

Then I would create a a basic form helper that would wrap these explanations inside of a span (initially hidden and shown via jQuery) so they could be instatiated via f.field_description(:title) or something along those lines.

Anyone have any better ideas? I'd like to keep this field metadata in the model since many views could use the same information, and I also think it's nice to have descriptions within the model when you're going back to look at the code (like how DataMapper can be used right within the model to specify fields).

To give you a little more detail on what I've already done (and it works fine) here's the code. I think there has to be a prettier way of expressing these descriptions in the model, so let me know if you have any ideas.

In model:

FIELD_DESCRIPTIONS = {
  'category' => 'Select the category it should appear within.',
  'title' => 'The title should be a short but descriptive summary.',
  'description' => 'Please enter a full description.'
}

def self.describe_field(field)
  FIELD_DESCRIPTIONS[field]
end

In application_helper.rb

def field_helper(form, field)
  "<span class='field_helper'>#{form.object.class.describe_field(field)}</span>"
end

In view:

<%= field_helper(f, 'title') %>

This will produce the desired output:

<span class='field_helper'>The title should be a short but descriptive summary.</span>

UPDATE:

Ok So this is the final code I'm using based on the accepted answer.

File: /config/initializers/describe_attr.rb

if defined?(ActiveRecord)

  # let's us add attribute descriptions to each AR model
  class ActiveRecord::Base
    def self.describe_attr(*params)
      attrs = params.shift
      unless attrs.nil?
        case attrs
          when Hash
            @@attr_descriptions = attrs
          when Symbol
            return @@attr_descriptions[attrs]
        end
      end 
      @@attr_descriptions ||= {}
    end
  end

end

File: /app/models/project.rb

describe_attr(
    :category => 'Select the category the project should appear within.',
    :title => 'The title should be a short but descriptive summary of the project.',
    :description => 'Describe the project in detail.',
    :image => 'Upload an image for the project.'
)

File: /app/helpers/application_helper.rb

# assumes you have a style defined for attr_description
def describe_attr(form, attribute)
    "<span class='attr_description'>#{form.object.class.describe_attr(attribute)}</span>"
end

File: /app/views/projects/_form.html.erb

<%= describe_attr(f, :title) %>
like image 655
Dave Rapin Avatar asked Oct 27 '25 09:10

Dave Rapin


2 Answers

The hash is a reasonable simple solution, but if you're on rails 2.2 or higher you might want to try the internationalization api to do this. This would also put you in a good place if you ever wanted to add translations.

Check out the i18n guide for details, but basically you would create a config/locales/en.yml that includes your column names like:

en:
  labels:
    category: Select the category it should appear within.

Then in your view:

<%= t('labels.category') %>

The namespace is your call of course. Also check out section 4.1.4 for a neat way to separate translations based on your current view template.

like image 127
Mat Schaffer Avatar answered Oct 30 '25 00:10

Mat Schaffer


If you want to patch ActiveRecord, then you can do something like:

# Add this at the bottom of enviroment.rb
class ActiveRecord::Base
  def self.field_description(*params)
    attrs = params.shift
    unless attrs.nil?
      case attrs
        when Hash
          @@field_description = attrs
        when Symbol
          return @@field_description[attrs]
        end
      end 
      @@field_description ||= {}
    end
end

And inside your model you can add this line like a macro:

class Product < ActiveRecord::Base

  field_description  :category => 'Select the category it should appear within.',:title => 'The title should be a short but descriptive summary.',:description => 'Please enter a full description.'

end

To get the value

Product.field_description : title
like image 39
khelll Avatar answered Oct 30 '25 01:10

khelll