Лучший способ расширить состояния AASM restful_authentication
-
07-07-2019 - |
Вопрос
Недавно мне пришлось расширить состояния AASM для последней версии restful_authentication (github) в одном из моих приложений. Я удалил «включить авторизацию :: AasmRoles», скопировал существующие состояния и события из плагина и внес изменения, необходимые для поддержки дополнительной «опубликованной» информации. указать модель моего аккаунта.
У кого-нибудь есть более чистый способ справиться с этим? То есть просто переопределить состояние событий? Я смог добавить новые события с помощью плагина как есть, однако я не смог просто переопределить события состояния уже в restful_auth, поэтому мне пришлось удалить и включить его самостоятельно, используя его в качестве отправной точки.
Решение
Добавление состояния в AASM состоит из создания нового объекта State, который затем добавляется в массив AASM :: StateMachine [User] .states, который выглядит следующим образом:
def create_state(name, options)
@states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name)
end
Здесь следует отметить, что он не позволяет переопределить состояние после его установки. Если состояние с тем же именем устанавливается снова, метод create_state просто игнорирует его. Чтобы решить эту проблему, вы можете использовать что-то подобное в своей модели User:
# this will remove the state with name :name from the states array
states = AASM::StateMachine[self].states
states.delete(states.find{ |s| s == :name })
# ... so we can define the state here again
aasm_state :name ...
Если вы просто переопределяете состояние, у вас все будет хорошо. Но если вы хотите полностью удалить состояние, вам также следует отменить определение метода, определенного в теле метода aasm_state. Это должно быть возможно при вызове чего-то вроде:
undef_method :name
Ситуация должна быть такой же с событиями (просто используйте «события» вместо «состояний» в коде). В идеале, сделайте это методом класса пользовательской модели, который переопределяет методы, определенные в модуле AASM. В случае состояний это будет выглядеть так:
def aasm_state(name, options={})
states = AASM::StateMachine[self].states
states.delete(states.find{ |s| s == name.to_sym })
super(name, options)
end
Предупреждение: возможно, я не прав. Этот код не тестировался, я только что понял его, изучив исходный код AASM.