Добавление удобочитаемых описаний полей в модели ActiveRecord

Я хотел бы добавить описания к полям модели ActiveRecord, которые будут служить базовыми инструкциями / примерами для каждого из полей. В основном метаданные модели. Затем я могу отобразить их в пользовательском интерфейсе (рядом с полями в форме и т. Д.)

Я планирую просто создать статическую хеш-таблицу внутри модели с именем поля в качестве ключа и описанием в качестве значения. Т.е.

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.'
}

и т.п.

Затем я бы создал базовый помощник формы, который обернул бы эти объяснения внутри диапазона (изначально скрытого и показанного через jQuery), чтобы их можно было установить через f.field_description (: title) или что-то в этом роде.

У кого-нибудь есть идеи получше? Я хотел бы сохранить метаданные этого поля в модели, поскольку многие представления могут использовать одну и ту же информацию, и я также думаю, что хорошо иметь описания в модели, когда вы вернетесь, чтобы посмотреть на код (например, как DataMapper может быть используется прямо в модели для указания полей).

Чтобы подробнее рассказать о том, что я уже сделал (и он отлично работает), вот код. Я думаю, что должен быть более красивый способ выразить эти описания в модели, поэтому дайте мне знать, если у вас есть какие-либо идеи.

В модели:

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

В application_helper.rb

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

Ввиду:

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

Это даст желаемый результат:

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

ОБНОВЛЕНИЕ:

Хорошо. Итак, это последний код, который я использую на основе принятого ответа.

Файл: /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

Файл: /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.'
)

Файл: /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

Файл: /app/views/projects/_form.html.erb

<%= describe_attr(f, :title) %>

person Dave Rapin    schedule 29.09.2009    source источник


Ответы (4)


Если вы хотите исправить ActiveRecord, вы можете сделать что-то вроде:

# 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

А внутри модели вы можете добавить эту строку как макрос:

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

Чтобы получить значение

Product.field_description : title
person khelll    schedule 29.09.2009
comment
Ты сделал это. Мне очень нравится такой способ справиться с этим. По ощущениям чище, чем константа хеш-таблицы в модели, которую я делал. - person Dave Rapin; 30.09.2009

Хэш - разумное простое решение, но если вы используете rails 2.2 или выше, вы можете попробовать API интернационализации, чтобы сделать это. Это также поможет вам, если вы когда-нибудь захотите добавить переводы.

Ознакомьтесь с руководством по i18n для получения подробной информации, но в основном вы должны создать config / locales / en. yml, который включает имена ваших столбцов, например:

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

Тогда, на ваш взгляд:

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

Пространство имен - это, конечно, ваше призвание. Также ознакомьтесь с разделом 4.1.4, чтобы узнать о аккуратном способе разделения переводов на основе вашего текущего шаблона представления.

person Mat Schaffer    schedule 29.09.2009
comment
Если по какой-то причине он не соответствует вашим потребностям (и я не могу себе представить, почему), это определенно правильный путь. Плагины и драгоценные камни, которые должны использовать эти описания, будут искать здесь. - person James A. Rosen; 29.09.2009
comment
Это действительно отличное решение. Единственная проблема, с которой я столкнулся, заключается в том, что он удаляет описания из контекста модели. Описания полей также могут служить комментариями к данным, которые хранятся в модели, и было бы гораздо лучше иметь их в самой модели. Однако, если мне когда-либо приходилось поддерживать интернационализацию, это определенно лучший способ ее решить. - person Dave Rapin; 30.09.2009
comment
Я чувствую твою боль, Дэйв, но думаю, что что-нибудь вроде agilewebdevelopment.com/plugins/annotate_models было бы лучше решение для ссылки на атрибут встроенной модели. - person Mat Schaffer; 09.10.2009

Вы можете смешать свое решение с самим помощником label:

f.label :title, f.describe(:title)

И в вашей модели:

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 describe(:field)
  self.class::FIELD_DESCRIPTIONS[field]
end
person khelll    schedule 29.09.2009
comment
Это хорошая идея, но на самом деле я хочу, чтобы метка и описание были разделены. Описание появится только после того, как пользователь щелкнет ссылку на значок справки (через jquery). Я просто напишу помощника, чтобы справиться с этим. В любом случае, я действительно спрашивал, есть ли у кого-нибудь лучшая идея, как использовать хеш-таблицу в модели для прикрепления описаний к ее свойствам. Т.е. динамически добавлять методы object.field_description или что-то подобное. - person Dave Rapin; 29.09.2009

Обязательно ознакомьтесь с formtastic, который включает поддержку интернационализированных (или нет) меток полей в соответствии с ответом matschaffer.

http://github.com/justinfrench/formtastic/

person sheldonh    schedule 30.09.2009
comment
Выглядит отлично. Я собираюсь поиграть с этим. Атрибут подсказка - это в основном то, что я создавал. - person Dave Rapin; 30.09.2009