Как создать объект подкласса STI с помощью ActiveAdmin
Учитывая следующую настройку (которая не работает в настоящее время)
class Employee < ActiveRecord::Base
end
class Manager < Employee
end
ActiveAdmin.register Employee do
form do |f|
f.input :name
f.input :joining_date
f.input :salary
f.input :type, as: select, collection: Employee.descendants.map(&:name)
end
end
Я хотел бы иметь единую "новую" форму для всех сотрудников и иметь возможность выбрать тип STI сотрудника в форме. Я могу видеть поле выбора для "типа", как и предполагалось, но когда я нажимаю кнопку "Создать", я получаю следующую ошибку:
ActiveModel::MassAssignmentSecurity::Error in Admin::EmployeesController#create
Can't mass-assign protected attributes: type
Теперь я знаю, как работают защищенные атрибуты в Rails, и у меня есть несколько обходных путей, таких как определение Employee.attributes_protected_by_default
но это снижает безопасность и слишком хакерский.
Я хочу быть в состоянии сделать это с помощью какой-либо функции в ActiveAdmin, но я не могу ее найти. Я не хочу создавать собственное действие контроллера, так как пример, который я показал, очень упрощен и надуман.
Я хотел бы, чтобы каким-то образом контроллер, сгенерированный ActiveAdmin, идентифицировал type
и делать Manager.create
вместо Employee.create
Кто-нибудь знает обходной путь?
1 ответ
Вы можете настроить контроллер самостоятельно. Прочитайте документ ActiveAdmin по настройке контроллеров. Вот быстрый пример:
controller do
alias_method :create_user, :create
def create
# do what you need to here
# then call create_user alias
# which calls the original create
create_user
# or do the create yourself and don't
# call create_user
end
end
Более новые версии
inherited_resources
gem имеет модуль BaseHelpers. Вы можете переопределить его методы, чтобы изменить способ изменения модели, сохранив при этом весь окружающий код контроллера. Это немного чище, чем
alias_method
, и у них есть хуки для всех стандартных действий REST:
controller do
# overrides InheritedResources::BaseHelpers#create_resource
def create_resource(object)
object.do_some_cool_stuff_and_save
end
# overrides InheritedResources::BaseHelpers#destroy_resource
def destroy_resource(object)
object.soft_delete
end
end