我有我的Rails应用程序的类Importer,其中我使用方法导入CSV文件。
def import
CSV.foreach(file.path, headers: true, encoding: "iso-8859-1") do |row|
mail = row["email"]||row["Email"]||row["e-mail"]||row["E-mail"]||row["mail"]||row["Mail"]
end
end
我设置变量mail
来执行循环内的操作,我尝试保护它不受邮件列的不同名称的影响,但是我不知道如何在没有任何已定义列的CSV的情况下断开循环并保留代码DRY头。
编辑:
def import
header = nil
headers = CSV.open(file.path, encoding: "iso-8859-1") { |csv| csv.first }
headers.each { |e| header = e if e.downcase.gsub('-','')=~/^(|e)mail$/ }
if header != nil
CSV.foreach(file.path, headers: true, encoding: "iso-8859-1") do |row|
mail = row[header]
end
end
end
解决问题的方法
这应该让你开始。您需要更改正则表达式以匹配所有情况。
def import
CSV.foreach(file.path, headers: true, encoding: "iso-8859-1") do |row|
if row.headers.none?{|e| e =~ /email/i}
raise "freak out"
end
end
end
我还会考虑设置一个你可以检查的变量has_email_headers
,因为你不想扫描每一行的标题,因为它们都是一样的。
根据CSV documentation of Ruby 2.5.0,您也可以使用return_headers:true
在循环中检查header_row?
。这是一个例子:
data = CSV.read("your.csv", headers: true, return_headers: true)
(0..(data.length-1)).each do |row|
if data[row].header_row? then
p "yes header!"
end
end
曾经也可以尝试使用header_converters: [:downcase, :symbol]
选项,只需检查更少的值(即不区分大小写),例如[:email, :mail]
:
CSV.foreach(file.path, headers: true, header_converters: [:downcase, :symbol], encoding: "iso-8859-1") do |row|
puts 'You are missing the "email" header!' unless [:email, :mail].all? { |header| row.headers.include? header }
# refine/refactor as necessary...
# do rest of function...
end
有关:header_converters的文档。