Лучший способ создать атрибут типа на ваших моделях Ruby on Rails

Понимание структур данных в Ruby / Rails - простой способ повысить скорость разработки.

Перечисления предназначены для занесения в белый список и определения «типов» экземпляров модели.

Перечисления (представленные в Rails 4.1) - это функция Rails, а не Ruby.

Но есть ли перечисления ARE?

Перечисления - это постоянные преобразования значений в целые числа.

Они константы. Они определены заранее и не меняются.

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

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

Пример перечисления, как определено в модели

enum item_type: {
    fruit: 0,
    vegetable: 10,
    meat: 20,
    bread: 30
}

Альтернатива: постоянные хэши

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

ITEM_TYPE = {
    fruit: 0,
    vegetable: 10,
    meat: 20,
    bread: 30
}

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

Они не только подразумевают «типаж», но и творит классную магию за кулисами (о которой мы скоро поговорим).

Еще пара примеров, где могут применяться перечисления.

pet.rb имеет перечисление с именем species, которое может быть только dog, fish или cat.

car_part.rb имеет перечисление с именем status, которое может быть только одним из in_development, in_production, obsolete или unknown.

Перечисления могут быть определены как массивы или хэши.

Есть два способа определить перечисления, но я рекомендую последний.

Перечисление массива

enum status: [:available, :discontinued, :pending]

Хеш-перечисление

enum status: {
    available: 0,
    discontinued: 10,
    pending: 20
}

Первый более лаконичен, но лишен гибкости. Второй вариант более расширяемый, потому что вы можете выбирать, какие целые числа использовать.

Перечисления - это целые числа в миграциях

При создании столбцов в миграции, которые вы хотите использовать с перечислением, установите для столбцов значение integer.

Ниже приведен переход для создания items таблицы, в которой каждый товар представляет отдельный продукт в супермаркете.

class CreateItems < ActiveRecord::Migration[6.0]
  def change
    create_table :items do |t|
      t.string :name
      t.integer :item_type, default: 0
      t.integer :status, default: 0
      t.timestamps
    end
  end
end

Соответствующий файл модели, item.rb

class Item < ApplicationRecord
  
  enum status: {
      available: 1,
      discontinued: 2,
      pending: 3}

  enum item_type: {
      fruit: 10,
      vegetable: 20,
      meat: 30,
      bread: 40}

end

Теперь вы можете использовать ключ или значение при сохранении записи.

Item.new(
  name:'Tomato', 
  status:'available', # KEY
  item_type:10)       # VALUE

Обратите внимание, что если введенные вами данные не соответствуют парам "ключ-значение" в перечислении, будет выдано сообщение об ошибке.

Active Record автоматически преобразует строки в целые числа

Это круто.

На уровне Rails значениями являются строки перечисления.

#<Item 
  id: 2, 
  name: "Tomato", 
  item_type: "fruit", 
  status: "available", 
  created_at: "2020-11-20 18:53:19", 
  updated_at: "2020-11-20 18:53:19">

Но на уровне базы данных значения - это целые числа перечисления.

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

Итак, если мы изменим наше перечисление с this.

enum item_type: {fruit: 10...}

К этому.

enum item_type: {sweet_fruit: 10...}

Загруженные записи автоматически получают новое строковое значение “sweet_fruit”.

#<Item 
  id: 2, 
  name: "Tomato", 
  item_type: "sweet_fruit", 
  status: "available", 
  created_at: "2020-11-20 18:53:19", 
  updated_at: "2020-11-20 18:53:19">

Некоторые другие функции

Несколько методов добавляются по умолчанию к любому столбцу со связанным перечислением.

Вопросительные знаки

Возвращает истину, если текущее значение перечисления совпадает.

Item.last.sweet_fruit?
=> true
Item.last.meat?
=> false

Пояснительные знаки

Обновляет значение.

Item.last.item_type => "sweet_fruit"
Item.last.meat!
Item.last.item_type => "meat"

Советы по наилучшему использованию перечислений

  1. Для определения перечислений используйте хэши, а не массивы. Это позволяет вам устанавливать целые числа самостоятельно.
  2. Не используйте последовательные целые числа при определении перечисления. Используйте 10, 20, 30… вместо 1, 2, 3…. Это дает больше места для добавления новых ключей / значений в будущем. Если овощ 20, а мы хотим добавить root_vegetable, я бы предпочел добавить его как 21, а не в конец списка.

Заключение

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

В отличие от других языков, они являются особенностью фреймворка (Rails), а не языка (Ruby). Тем не менее, их связь с Rails обеспечивает уникальные преимущества, такие как автоматическое преобразование строк в целые числа во время сохранения / загрузки.

Дайте знать в комментариях, если я что-то упустил!

Как всегда, удачного кодирования.