如何 select 一个模型字段来表示活动管理仪表板上的多对一关系?

How to select a model field to represent a many to one relationship on active admin dashboard?

我正在使用 rails 5 和 activeadmin gem 建立一个电子商务网站来管理我的仪表板。我在多对一关系中有一个产品和一个类别模型。

class Product < ApplicationRecord
    before_destroy :not_referenced_by_any_line_item
    belongs_to :category
    has_many :line_items, dependent: :destroy
    has_many :reviews, dependent: :destroy

    def self.search(search)
        all.where("lower(title) LIKE :search", search: "%#{search}%")
    end 

    private

    def not_referenced_by_any_line_item
        unless line_items.empty?
            errors.add(:base, "line items present")
            throw :abort
        end
    end
end
class Category < ApplicationRecord
    has_many :products, dependent: :destroy

    def self.search(search)
        all.where("lower(category_name) LIKE :search", search: "%#{search}%")
    end 
end

然后我将模型注册到 activeadmin 仪表板,如下所示

ActiveAdmin.register Product do

  permit_params :title, :description, :availability, 
  :price, :photo_link, :category_id, :advert, :pictureOne, 
  :pictureTwo, :pictureThree

end

ActiveAdmin.register Category do

  permit_params :category_name, :photos

end

我现在可以在创建产品时 select 项目表单上的产品类别,但问题是,项目类别表单输入字段上显示的不是类别名称或任何其他字段,因此您确切地知道您 select 属于哪个类别,正在显示一个卑鄙的人,因此很难知道您 select 属于哪个类别。产品类别输入表单字段下拉列表的显示:

ActiveAdmin 的默认功能是在决定将什么呈现为记录标识符时在给定模型上查找 name 字段。如果模型没有 name 字段,ActiveAdmin 除了能够向您显示该记录在内存中的位置的字符串化混乱之外,不会让您知道您正在处理的记录(如果您在控制台中执行 Category.first.to_s,则会得到相同的字符串。

要让 ActiveAdmin 识别名称,您必须覆盖它为您创建的默认编辑表单,以便您可以自定义 select 标签。

您需要将所有要编辑的字段添加到表单中。当您为类别添加输入时,您指定希望该字段为 select,并且您可以自定义 select 的标签,如下所示:

# app/admin/product.rb

ActiveAdmin.register Product do
  permit_params :title, :description, :availability, 
  :price, :photo_link, :category_id, :advert, :pictureOne, 
  :pictureTwo, :pictureThree

  form do |f|
    f.inputs do
      # Add a form input for the category
      #
      # This approach also allows you to specify which categories you 
      # allow to be selected, in the "collection" attribute.
      #
      # Inside the "map" call, you have the proc return an array with the first item 
      # in the array being the name of the category (the label for the select) 
      # and the second item being the category's ID (the select's value)
      f.input :category_id, label: 'Category', as: :select, collection: Category.all.map{ |c| [c.category_name, c.id]}

      # Then add other inputs
      f.input :title
      f.input :description
      f.input :availability

      # ...
      # (Add f.input for the rest of your fields)
    end

    f.actions
  end
end

当您需要在 ActiveAdmin 的其他地方将名称呈现为类别时,您将遵循类似的方法。

如果不太麻烦,您最好将类别模型上的 category_name 重命名为 name。这样,您与 ActiveAdmin 的斗争就会少很多,并且不需要像这样进行太多的自定义。