Подтвердить что ты не робот

Надлежащее хранение моделей "перечисления" в Rails

Извините, если вопрос немного неточен, но я опишу свою проблему ниже.

Я создаю некоторые модели в проекте Rails, и одна вещь, которую я заметил, что я работаю более чем несколько раз, имеет дело с атрибутами, которые отвечают следующим критериям:

  • Они могут быть установлены в один из небольшого предопределенного набора значений
  • Эти значения должны иметь как имя, так и идентификатор (будь то числовой код, код, что угодно)
  • Значения будут меняться только в результате большого изменения кода.

Например, одна из моих моделей должна иметь поле status, которое может быть установлено в одно из: Определение, Выполнение или Завершено. Мне нужно показать эти конкретные слова в интерфейсе, но я не хочу хранить строки в БД, если мне нужно изменить их в будущем (или интернационализировать или что-то еще.)

Очевидным вариантом является определение моделей для каждой из этих моделей, но это, как представляется, создает значительные накладные расходы на поддержание моделей, гарантируя, что я пишу миграции между средами и т.д. для каждого из них, что похоже на много накладных расходов.

Другой вариант заключается в том, чтобы сохранить его как целое число и поднять класс типа "перечисление", который сохраняет перевод этих значений - это, вероятно, будет работать нормально, но я обеспокоен тем, что потеряю ассоциации и другие удобный материал, который я получаю от моделей ActiveRecord.

Любые советы по наилучшему способу справиться с этой ситуацией?

4b9b3361

Ответ 1

Посмотрите на рубиновый драгоценный камень, над которым я работал, называемый classy_enum. Я уверен, что он делает именно то, что вы ищете. README использует некоторые примеры использования, но предпосылка заключается в том, что он позволяет определять несколько членов enum как классы, которые могут иметь разные свойства.

Ответ 2

Определите varchar или ENUM в базе данных и подтвердите поле в модели:

validates_inclusion_of :status, :in => %w(Defining Executed Completed)

Rails будет обрабатывать его как строковое поле, но он все еще проверяет, что такое значения.

Если вам действительно нужно абстрагировать текст поля состояния, вы можете просто сохранить его как целое число:

class Foo < ActiveRecord::Base
  STATUS_DESCRIPTIONS = %w(Defining Executed Completed)

  def status
    STATUS_DESCRIPTIONS[ read_attribute(:status) ]
  end
end

Если это становится более сложным, вам следует попробовать gem @Beerlington.

Ответ 3

Я искал подобное решение, когда столкнулся с enumerize gem. Мне нравится его чистая и простая DSL.

Если ваши штаты содержат много знаний о конкретном государстве, то предложенный scaney генератор состояний может быть хорошей идеей. Другой вариант заключается в использовании старого старого шаблона состояния с state_pattern gem.

Ответ 5

Как разместить его в модуле и смешать его с моделями:

module StatusCodes
  DEFINING = 1
  EXECUTING = 2
  COMPLETED = 3

  def status
    return "" unless self[:status] # handle nil
    const_lookup = self[:status] - 1 # index to module constants
    StatusCodes.constants[const_lookup].to_s.downcase.camelcase # note: needs Ruby 1.9
  end
end

class MyModel < ActiveRecord::Base
  include StatusCodes
end

Теперь добавьте целочисленный столбец status в модель, и вы можете назначить так:

m = MyModel.new(:status=>StatusCodes::DEFINING)

и получить строку:

m.status # "Defining"

Ответ 6

вместе с другими превосходными параметрами, вы можете использовать это, если вы выберете свой последний вариант:

http://github.com/jasondew/coded_options

(используется для работы с Jason, и мы использовали предшественника для этого в нескольких приложениях rails, особенно если пользователь когда-либо выбирает эту опцию из тега select)

Ответ 7

Только для полноты, Rails имеет класс Enum начиная с версии 4.1.