Ruby on Rails ActiveRecord: как мне сохранить состояние объекта? - PullRequest
3 голосов
/ 06 марта 2012

У меня есть модель User, которая имеет состояние.Состояние может быть одним из следующих: ['непроверено', 'активно', 'удалено']

Каков наилучший способ сохранить состояние объекта в базе данных?

СледуетЯ создаю три логических поля?Это не имело бы большого смысла, так как я мог бы хотеть легко расширить число состояний, и только одно состояние может быть «истинным» одновременно.

Должен ли я использовать state_machine Драгоценный камень только для простого переключения постоянных значений?

Или есть какой-либо другой распространенный способ, лучшая практика или простой драгоценный камень для такого рода работы?

Ответы [ 5 ]

17 голосов
/ 07 марта 2012

Очень простое решение, которое я использовал для этого:

В вашей миграции

add_column :users, :state, :string

В вашей модели

class User < ActiveRecord::Base

  STATES = %w{ unverified active deleted }

  STATES.each do |state|
    define_method("#{state}?") do
      self.state == state
    end

    define_method("#{state}!") do
      self.update_attribute(:state, state)
    end
  end
end

Тогда вы можете позвонить

@user.active? # => returns true/false

Или

@user.active! # => sets the users state to active
3 голосов
/ 07 марта 2012

Если вы используете Rails3 с базой данных MySQL, вы можете использовать enum_column . Он предоставляет столбец :enum для использования при переносе, а также метод проверки. Он также предоставляет помощник вида enum_select.

1 голос
/ 07 марта 2012

Вы можете использовать перечислимый тип для хранения состояния в виде простого целого числа.Я обычно использую драгоценный камень active_enum , чтобы сделать это простым.Это будет выглядеть примерно так:

class User

  # An enumerated type representing the current state of the user
  enumerate :state do
    value name: "unverified"
    value name: "active"
    value name: "deleted"
  end

end

Это позволит вам проверить состояние следующим образом

# check if active
user.state?(:active)

Просто убедитесь, что у вас есть целое поле с именем state (иливсе, что вы хотите назвать перечислимым типом) в таблице User.

Подробнее см. в документации gem .

1 голос
/ 07 марта 2012

Не используйте логические поля.

Если названия состояний похожи на «ключи» и вряд ли изменятся, вы можете просто сохранить их в виде текстовых полей в базе данных.Просто добавьте миграцию с помощью

add_column :users, :state, :string

. Когда вы сохраняете ваш объект, он принимает user.state и сохраняет символ в виде строки «непроверенный», «активный» и т. Д.

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

rails g model State name:string

rails создаст файл модели и перенастроим для них.Затем измените миграцию следующим образом:

add_column :users, :state_id, :integer

Вы можете заполнить список состояний непроверенными, активными и т. Д. Либо непосредственно в sql, либо через начальное число, либо через существующую миграцию.Вы также можете создать внешний ключ между ними, если хотите.

Тогда в вашем коде для установки состояния вы должны использовать это:

user.state = State.find_by_name(:unverified)
1 голос
/ 07 марта 2012

Я бы оставил это как ноль, «активный», «удаленный». Если вы хотите иметь дополнительные перехватчики процессов при переключении состояния, такие как электронные письма, отправленные, то гем state_machine был бы полезен. Кроме того, если вы хотите иметь дополнительную аналитику, например, когда кто-то переходил от непроверенного к активному, может быть полезно иметь «active_on_date» и сохранять его как дату и время, когда произойдет переход.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...