我想通过activeadmin面板上传CSV文件。
在资源“product”的索引页面上我想要一个带有“import csv file”的“new product”按钮旁边的按钮。
我不知道从哪里开始。 在文档中是关于collection_action的东西,但是使用下面的代码我顶部没有链接。
ActiveAdmin.register Post do
collection_action :import_csv, :method => :post do
# Do some CSV importing work here...
redirect_to :action => :index, :notice => "CSV imported successfully!"
end
end
这里有谁使用activeadmin并且可以导入csv数据?
答案 0 :(得分:42)
继续托马斯·沃特森的良好开端,帮助我在确定其余部分之前找到了答案。
代码打击不仅允许示例Posts模型的CSV上传,还允许其后的任何后续模型。您需要做的就是将action_item和示例中的collection_actions复制到任何其他ActiveAdmin.register块中,功能将相同。希望这有帮助。
应用/管理/ posts.rb 强>
ActiveAdmin.register Post do
action_item :only => :index do
link_to 'Upload CSV', :action => 'upload_csv'
end
collection_action :upload_csv do
render "admin/csv/upload_csv"
end
collection_action :import_csv, :method => :post do
CsvDb.convert_save("post", params[:dump][:file])
redirect_to :action => :index, :notice => "CSV imported successfully!"
end
end
应用/模型/ csv_db.rb 强>
require 'csv'
class CsvDb
class << self
def convert_save(model_name, csv_data)
csv_file = csv_data.read
CSV.parse(csv_file) do |row|
target_model = model_name.classify.constantize
new_object = target_model.new
column_iterator = -1
target_model.column_names.each do |key|
column_iterator += 1
unless key == "ID"
value = row[column_iterator]
new_object.send "#{key}=", value
end
end
new_object.save
end
end
end
end
注意:此示例检查第一列是否为ID列,然后跳过该列,因为rails将为新对象分配ID(请参阅下面的示例CSV以供参考)< / em>的
应用/视图/管理/ CSV / upload_csv.html.haml 强>
= form_for :dump, :url=>{:action=>"import_csv"}, :html => { :multipart => true } do |f|
%table
%tr
%td
%label{:for => "dump_file"}
Select a CSV File :
%td
= f.file_field :file
%tr
%td
= submit_tag 'Submit'
应用/公共/ example.csv 强>
"1","TITLE EXAMPLE","MESSAGE EXAMPLE","POSTED AT DATETIME"
"2","TITLE EXAMPLE","MESSAGE EXAMPLE","POSTED AT DATETIME"
"3","TITLE EXAMPLE","MESSAGE EXAMPLE","POSTED AT DATETIME"
"4","TITLE EXAMPLE","MESSAGE EXAMPLE","POSTED AT DATETIME"
"5","TITLE EXAMPLE","MESSAGE EXAMPLE","POSTED AT DATETIME"
注意:并非总是需要报价
答案 1 :(得分:13)
添加collection_action
不会自动添加链接到该操作的按钮。要在索引屏幕顶部添加按钮,您需要将以下代码添加到ActiveAdmin.register
块中:
action_item :only => :index do
link_to 'Upload CSV', :action => 'upload_csv'
end
但在调用您在问题中发布的收集操作之前,您首先需要用户指定要上载的文件。我个人会在另一个屏幕上执行此操作(即创建两个集合操作 - 一个是:get
操作,另一个是:post
操作。所以完整的AA控制器看起来像这样:
ActiveAdmin.register Post do
action_item :only => :index do
link_to 'Upload posts', :action => 'upload_csv'
end
collection_action :upload_csv do
# The method defaults to :get
# By default Active Admin will look for a view file with the same
# name as the action, so you need to create your view at
# app/views/admin/posts/upload_csv.html.haml (or .erb if that's your weapon)
end
collection_action :import_csv, :method => :post do
# Do some CSV importing work here...
redirect_to :action => :index, :notice => "CSV imported successfully!"
end
end
答案 2 :(得分:6)
@krhorst,我试图使用你的代码,但不幸的是它很糟糕的大进口。它吃了太多的内存=(所以我决定使用基于activerecord-import gem的自己的解决方案
这是https://github.com/Fivell/active_admin_import
功能
答案 3 :(得分:2)
为了将来的参考,我构建了一个gem,可以让你轻松地将csv import添加到活动的管理资源
答案 4 :(得分:2)
根据ben.m excellent answer上面的内容,我替换了建议的csv_db.rb
部分:
require 'csv'
class CsvDb
class << self
def convert_save(model_name, csv_data)
begin
target_model = model_name.classify.constantize
CSV.foreach(csv_data.path, :headers => true) do |row|
target_model.create(row.to_hash)
end
rescue Exception => e
Rails.logger.error e.message
Rails.logger.error e.backtrace.join("\n")
end
end
end
end
虽然不是一个完整的答案,但我不希望我的修改会污染ben.m的答案,以防我做了一些非常错误的事情。
答案 5 :(得分:0)
扩展ben.m的反应,我发现它非常有用。
我遇到了CSV导入逻辑的问题(属性没有排列,列迭代器没有按要求运行)并实现了一个更改,而是使用了每行循环和model.create方法。这允许您导入带有与属性匹配的标题行的.csv。
应用/模型/ csv_db.rb 强>
require 'csv'
class CsvDb
class << self
def convert_save(model_name, csv_data)
csv_file = csv_data.read
lines = CSV.parse(csv_file)
header = lines.shift
lines.each do |line|
attributes = Hash[header.zip line]
target_model = model_name.classify.constantize
target_model.create(attributes)
end
end
end
end
因此,导入的CSV文件可能如下所示(用于匹配模型属性):
<强> importExample.csv 强>
first_name,last_name,attribute1,attribute2
john,citizen,value1,value2
答案 6 :(得分:0)
答案 7 :(得分:0)
上面的某些解决方案效果很好。我在实践中遇到了一些挑战,这些挑战在下面解决。解决的问题是:
注意:我拿出了ID过滤器,以便可以针对自己的工作更改ID,但是大多数用例可能都希望保留它。
require 'csv'
class CsvDb
class << self
def convert_save(model_name, csv_data)
csv_file = csv_data.read
csv_file.to_s.force_encoding("UTF-8")
csv_file.sub!("\xEF\xBB\xBF", '')
target_model = model_name.classify.constantize
headers = csv_file.split("\n")[0].split(",")
CSV.parse(csv_file, headers: true) do |row|
new_object = target_model.new
column_iterator = -1
headers.each do |key|
column_iterator += 1
value = row[column_iterator]
new_object.send "#{key.chomp}=", value
end
new_object.save
end
ActiveRecord::Base.connection.reset_pk_sequence!(model_name.pluralize)
end
end
end