Как создать объект подкласса 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_resourcesgem имеет модуль 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
Другие вопросы по тегам