【问题标题】:Best way to do CSV seed file upload to rails repo through administrate?通过管理将 CSV 种子文件上传到 rails repo 的最佳方法?
【发布时间】:2021-02-17 17:39:34
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我认为,如果您希望最终用户能够通过 CSV 添加这些记录,您最好的选择是为文件上传添加一个脚手架,并在上传时为该表播种或播种通过其他方法(cron 等)并选择最新的文件。

标签: ruby-on-rails csv rails-administrate


【解决方案1】:

是的,这是可能的,而且您不需要 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 和一个提交按钮。提交时,它将文件作为 POST 请求发送到当前 URL (/admin/products/upload)。它将由我们之前添加的post 路由在操作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 cmets 之间,这样它就可以完全按照您的要求进行操作。有很多可能性。

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 2012-07-20
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多