如何使用ActiveAdmin创建STI子类的对象



给定以下设置(当前不工作)

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

有人知道变通办法吗?

您可以自己自定义控制器。阅读关于自定义控制器的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

最新更新