0

我后端的主表由 CSV 文件填充。播种和运行时,用读取rails db:seedCSV 文件,其中的逻辑遍历每一行以创建表条目,用 CSV 列数据填充字段。lib/assets/csvfile = File.read(Rails.root.join('lib', 'assets', 'csv', 'data.csv')seeds.rb

我还为 UI 管理仪表板实现了 Thoughtbot 的 Administrate 以查看这些数据。

所以我的问题是,如果我需要替换现有文件lib/assets/csv并重新播种,在管理仪表板上配置某种自定义文件上传系统的最佳方法是什么?

我看过 ActiveStorage,但我只用它来存储文件,比如专门与表条目相关的图像,而不是用于为整个表播种。

4

1 回答 1

0

是的,这是可能的,而且您不需要 ActiveStorage。Rails 的基本文件上传功能就足够了。同时,Administrate 尝试遵循 Rails 约定,并为您提供挂钩来更改模板并引用您自己的控制器和操作,您可以在其中实现这一点。这是一个如何解决问题的示例。

首先,您需要添加一个带有文件字段的表单。管理员将能够使用它来上传 CSV。

有很多地方可以放置此表格。对于此示例,假设您要导入的是“产品”(模型Product),并且您希望将链接放在索引页面中。

您可以用自己的模板覆盖 Administrate 自己的模板。以下命令将生成index您可以自定义的模板副本,Administrate 将使用它来代替它自己的:

$ ./bin/rails g administrate:views:index

这将为您提供一个新文件app/views/admin/application/index.html.erb

更改它以添加指向将托管上传表单的单独页面的链接:

  <% if page.resource_name == "product" %>
    <div class="link-to-upload"><%= link_to "CSV Import", upload_admin_products_path %></div>
  <% end %>

您可以将其放在页面标题和搜索栏之间。或者你想要的任何地方,真的。它执行以下操作:

  • 检查我们在“产品”的if索引页面中,而不是其他的东西。
  • link_to指向我们尚未创建的页面的链接,该页面将承载上传表单。

如果您现在加载产品索引页面,它将显示错误NameError,并带有消息undefined local variable or method 'upload_admin_products_path'。这是因为我们仍然没有新页面的路线。现在让我们添加它。

在路由文件config/routes.rb中,您已经有了一个路由resources :products。将其更改为如下所示:

    resources :products do
      collection do
        get :upload, action: 'upload_form'
        post :upload, action: 'upload_process'
      end
    end

这实际上增加了两条路线,而不是一条。一个用于表单页面,另一个用于处理上传的 CSV 的操作。

现在,您可以单击链接并转到新页面。它会再次破裂。这一次的错误将是 Unknown action - The action 'upload_form' could not be found for Admin::ProductsController。那是因为我们还没有提供这个页面的视图。让我们现在就开始做吧。

在以下位置添加具有以下内容的视图app/views/admin/products/upload_form.html.erb

<header class="main-content__header" role="banner">
  <h1 class="main-content__page-title" id="page-title">
    Import products from CSV
  </h1>
</header>

<section class="main-content__body main-content__body">
  <%= form_for :products, html: { class: "form" } do |f| %>
    <p><%= f.file_field(:file) %></p>
    <p><%= f.submit "Upload" %></p>
  <% end %>
</section>

现在您应该能够加载页面并查看表单。我添加了额外的标记(如那些headersection元素),使其看起来与 Administrate 提供的其他页面相似。

该表单有一个file_field和一个提交按钮。提交时,它会将文件/admin/products/upload作为 POST 请求发送到当前 URL ( )。它将由post我们之前添加的路由在 action 上处理upload_process。我们现在就写吧。

在控制器Admin::ProductsController上,添加以下方法来实现动作:

    def upload_process
      file = params[:products][:file]
      data = CSV.parse(file.to_io, headers: true, encoding: 'utf8')

      # Start code to handle CSV data
      ActiveRecord::Base.transaction do
        data.each do |row|
          Product.create(row.to_h)
        end
      end
      # End code to handle CSV data

      redirect_to admin_products_url
    end

这将根据 CSV 中包含的内容创建新产品,然后将用户重定向回产品索引页面。

此示例操作非常简单,可能无法完全满足您的需求。您可能想复制您的代码seeds.rb并将其粘贴在我的评论StartEnd评论之间,以便它完全按照您的意愿行事。有很多可能性。

于 2021-03-11T16:20:01.013 回答